package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.chargecalc.mchntfee.CalcMchntFee;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeBean;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeResultBean;
import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.*;
import cc.rengu.igas.momp.common.model.bean.SubsidyAmount;
import cc.rengu.igas.momp.common.util.JsonOperation;
import cc.rengu.igas.momp.common.util.MompDateUtil;
import cc.rengu.igas.momp.facade.bean.PaymentOrderCouponInfoBean;
import cc.rengu.igas.momp.facade.bean.PaymentOrderDetailBean;
import cc.rengu.igas.momp.facade.bean.PaymentOrderMoneyOffInfoBean;
import cc.rengu.igas.momp.facade.request.ComboPaymentRequest;
import cc.rengu.igas.momp.facade.response.ComboPaymentResponse;
import cc.rengu.jradp.mods.dbs.Database;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.BinInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.BinInfoService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.BinInfoServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.base.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * (合并)支付-减免\卡券\商户手续费优惠计算
 *
 * @author Jinan Liu
 * @since 2020/4/2 17:46
 */
public class ComboPaymentService extends RadpService {

    /**
     * 法人机构号
     */
    private String globalInstId;
    /**
     * 渠道交易流水号
     */
    private String globalTraceNo;
    /**
     * 渠道商户订单号
     */
    private String globalOrderId;
    /**
     * 用户ID
     */
    private String globalUserId;
    /**
     * 当前交易系统时间戳
     */
    private String globalTimeStamp;
    /**
     * 渠道交易日期
     */
    private String globalTxnDate;
    /**
     * 渠道交易时间
     */
    private String globalTxnTime;
    /**
     * 商户基本信息列表
     */
    private List<TBMchntBaseInfo> tbMchntBaseInfoList;
    /**
     * 订单信息
     */
    private TMTxnOrder tmTxnOrder;
    /**
     * 订单明细表
     */
    private List<TMTxnOrderDet> tmTxnOrderDetList;
    /**
     * 订单明细
     */
    private List<PaymentOrderDetailBean> paymentOrderDetailBeanList;
    /**
     * 对客户营销活动单日统计表
     */
    private List<TMStat2CDay> tmStat2CDayList;
    /**
     * 对客户营销活动商户单日统计表
     */
    private List<TMStat2CMchntDay> tmStat2CMchntDayList;
    /**
     * 手续费减免活动单日统计表
     */
    private List<TMStatMfdDay> tmStatMfdDayList;
    /**
     * 手续费减免活动商户单日统计表
     */
    private List<TMStatMfdMchntDay> tmStatMfdMchntDayList;
    /**
     * (合并)支付使用卡券类交易信息
     */
    private McCouponTxnData mcCouponTxnData = null;
    /**
     * 卡券基本信息
     */
    private TMCouponInfo tmCouponInfo = null;
    /**
     * 是否有优惠标志
     */
    private boolean globalDiscountFlag;
    /**
     * 流程是否正常标志
     */
    private boolean procNormalStatus;
    /**
     * 本笔交易手续费优惠金额累计
     */
    private List<TMStatMfdDay> statMfdDayList;
    private BigDecimal zero = BigDecimal.ZERO;

    /**
     * 对客营销活动用户统计表是否需要累加昨天数据
     */
    private int batchStatusStat = CommonConstant.FLAG_NOT_SET;
    /**
     * 对客营销活动用户月统计表是否需要累加昨天数据
     */
    private int batchStatusStatMonth = CommonConstant.FLAG_NOT_SET;
    /**
     * 是否设置了商户结算账户为对公户不允许参加营销活动
     */
    private static final String MOMP_DIFFERENTIATE_SETTLEACCTTYPE = "MOMP_DIFFERENTIATE_SETTLEACCTTYPE";
    /**
     * 用户标志  1：未上送useId 2：单个userId 3：json字符串
     */
    private String userIdFlag;
    /**
     * 营销用户类型 0：手机号 1：银行卡号 2：卡bin 3：卡产品
     */
    private String acctType;
    /**
     * 手机号
     */
    private String phoneNo;
    /**
     * 银行卡号
     */
    private String cardNo;
    /**
     * 微信Id
     */
    private String wechatId;
    /**
     * 支付宝Id
     */
    private String alipayId;
    /**
     * 优惠时所用的id
     */
    private String discountId;
    /**
     * 新商户入驻时间是否区分15号之前还是之后
     */
    private static final String MOMP_DISTINGUISH_MIDDLE_OF_MONTH = "MOMP_DISTINGUISH_MIDDLE_OF_MONTH";
    /**
     * 东营行机构代码
     */
    private static final String INST_ID_DY = "812";
    /**
     * 东营行新商户重复入网校验手续费优惠额度
     */
    private static final String DISCOUNT_AMOUNT = "40";
    /**
     * 满减活动数据
     */
    private List<PaymentOrderMoneyOffInfoBean> paymentOrderMoneyOffInfoBeanList;
    /**
     * 分期类型
     */
    private String stageType = "";
    /**
     * 分期期数
     */
    private String stageNum = "";
    /**
     * 分期code
     */
    private String stageCode = "";
    /**
     * 核心客户号
     */
    private String coreComId;

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        try {

            ComboPaymentRequest comboPaymentRequest = new ComboPaymentRequest();
            ConvertUtil.convertOutput(comboPaymentRequest);

            /* 检查请求报文并赋值全局变量 */
            messageValidation(comboPaymentRequest);

            ComboPaymentResponse comboPaymentResponse = new ComboPaymentResponse();
            comboPaymentResponse.setHeader(comboPaymentRequest.getHeader());
            BizResponse<ComboPaymentResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(comboPaymentResponse);

            /* 服务调用 */
            BizResponse<ComboPaymentResponse> bizResponseNew = comboPayment(xmlTreeUtil, comboPaymentRequest, comboPaymentResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());

        } catch (BizException e) {
            try {
                /* 确保任何情况下订单流水表都有记录存在 */
                procNormalStatus = false;
                onlyRecordTxnOrderInfo(xmlTreeUtil);

                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());

            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                /* 确保任何情况下订单流水表都有记录存在 */
                procNormalStatus = false;
                onlyRecordTxnOrderInfo(xmlTreeUtil);

                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());

            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * (合并)支付
     *
     * @param xmlTreeUtil          内部XML树
     * @param comboPaymentRequest  (合并)支付接口请求对象
     * @param comboPaymentResponse (合并)支付接口应答对象
     * @return cc.rengu.oltp.service.model.BizResponse<cc.rengu.igas.momp.facade.response.ComboPaymentResponse> (合并)支付接口应答对象
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/4 10:01
     */
    private BizResponse<ComboPaymentResponse> comboPayment(XmlTreeUtil xmlTreeUtil, ComboPaymentRequest comboPaymentRequest, ComboPaymentResponse comboPaymentResponse) throws Exception {

        BizResponse<ComboPaymentResponse> bizResponse = new BizResponse<>();

        int returnCode;

        /* 取商户基本信息,查询订单明细中所有商户对应的商户基本信息 */
        for (PaymentOrderDetailBean paymentOrderDetailBean : comboPaymentRequest.getOrderDetailList()) {

            checkOrderDetailFieldHasNegativeNumber(paymentOrderDetailBean);

            /* 根据商户编号查询商圈编号 */
            String mchntNo = paymentOrderDetailBean.getMchntNo();
            if (!StringUtil.isNullorEmpty(mchntNo)) {
                /* 查询商户基本信息表 */
                TBMchntBaseInfo tbMchntBaseInfo = selectMompMchntBaseInfoByPrimaryKey(globalInstId, mchntNo);
                if (null == tbMchntBaseInfo) {
                    rglog.error("查询法人机构<{}>商户<{}>基本信息失败!", globalInstId, mchntNo);
                    throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
                } else {
                    tbMchntBaseInfoList.add(tbMchntBaseInfo);
                }
            } else {
                rglog.error("需要上送商户编号!");
                throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            }
        }

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        /* 初始补贴字段赋值 */
        List<SubsidyAmount> subsidyAmountList = new ArrayList<>();
        for (PaymentOrderDetailBean paymentOrderDetailBean : paymentOrderDetailBeanList) {
            SubsidyAmount subsidyAmount = new SubsidyAmount();
            subsidyAmount.setMchntNo(paymentOrderDetailBean.getMchntNo());
            subsidyAmount.setOrderAmt(new BigDecimal(paymentOrderDetailBean.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP));
            subsidyAmount.setTotalSubsidy(BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP));
            subsidyAmount.setBankSubsidy(BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP));
            subsidyAmount.setMchntSubsidy(BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP));
            subsidyAmountList.add(subsidyAmount);
        }

        /*
         * 先处理卡券流程
         *  若卡券流程处理失败,不作任何满减的操作
         *  若卡券流程处理成功,继续满减操作处理流程
         *
         * 若任何满减活动计算失败,则该商户不进行优惠,其他商户优惠信息正常计算
         * */
        rglog.info("=========================================数据初始化完毕,开始处理卡券部分=========================================");
        returnCode = processCouponProcedure(comboPaymentRequest);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            /* 整个合并支付订单不再进行卡券优惠和满减优惠的计算,回滚所有数据库操作 */
            rglog.error("{}, TRACE_NO=<{}>, RETURN_CODE=<{}>", RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespDesc(),
                    comboPaymentRequest.getHeader().getTraceNo(), returnCode);
            dbsUtil.dbsEndTransaction(false);

            /* 确保任何情况下订单流水表都有记录存在 */
            procNormalStatus = false;
            onlyRecordTxnOrderInfo(xmlTreeUtil);

            /* 应答报文赋值 */
            comboPaymentResponse.setTransAmt(comboPaymentRequest.getTransAmt());
            comboPaymentResponse.setTxnAmt(comboPaymentRequest.getTransAmt());
            comboPaymentResponse.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
            comboPaymentResponse.setBankSubsidy(CommonConstant.ZERO_AMOUNT);
            comboPaymentResponse.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);

            bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
            bizResponse.setRespCode(RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespDesc());
            xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespDesc());

            comboPaymentResponse.setRespCode(RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespCode());
            comboPaymentResponse.setRespDesc(RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespDesc());

            bizResponse.setResult(comboPaymentResponse);

            return bizResponse;

        } else {
            /* 应答报文组装 添加卡券应答信息*/
            if (mcCouponTxnData != null) {

                for (PaymentOrderDetailBean paymentOrderDetailBean : comboPaymentRequest.getOrderDetailList()) {

                    if (paymentOrderDetailBean.getMchntNo().equals(mcCouponTxnData.getMchntNo())) {
                        /* 子订单有优惠*/
                        paymentOrderDetailBean.setCouponNo(mcCouponTxnData.getCouponNo());
                        paymentOrderDetailBean.setCouponMcNo(mcCouponTxnData.getMcNo());
                        paymentOrderDetailBean.setCouponDenomination(mcCouponTxnData.getCouponAmt());
                        paymentOrderDetailBean.setCouponPurchaseAmt(mcCouponTxnData.getPurchaseAmt());
                        paymentOrderDetailBean.setCouponTotalSubsidy(mcCouponTxnData.getTotalSubsidy());
                        paymentOrderDetailBean.setCouponBankSubsidy(mcCouponTxnData.getBankSubsidy());
                        paymentOrderDetailBean.setCouponMchntSubsidy(mcCouponTxnData.getMchntSubsidy());
                        paymentOrderDetailBean.setCouponMchntSettleMethod(mcCouponTxnData.getBudgetRechargeMethod());
                        paymentOrderDetailBean.setPurchaseFlag(mcCouponTxnData.getPurchaseFlag());
                    }
                }
            }

            rglog.info("=========================================卡券核销部分处理完毕,开始处理满减部分=========================================");
            int retCode = processMoneyOffProcedure(comboPaymentRequest, subsidyAmountList);
            rglog.debug("RETURN_CODE=<{}>", retCode);
            if (CommonConstant.PROCESS_SUCCESS != retCode) {
                /* 减免类营销活动业务流程处理失败 */
                rglog.error("{}, TRACE_NO=<{}>, RETURN_CODE=<{}>", RespCodeEnum.FAILED_TO_DISCOUNT_FOR_MO_MC_ERROR.getRespDesc(),
                        comboPaymentRequest.getHeader().getTraceNo(), returnCode);
//                dbsUtil.dbsEndTransaction(false);

                /* 应答报文赋值 */
                comboPaymentResponse.setTxnAmt(comboPaymentRequest.getTransAmt());
                comboPaymentResponse.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
                comboPaymentResponse.setBankSubsidy(CommonConstant.ZERO_AMOUNT);
                comboPaymentResponse.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);

            } else {

                /* 减免类营销活动业务流程处理成功 */
                BigDecimal orderAmt = new BigDecimal(comboPaymentRequest.getTransAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal totalSubsidy = BigDecimal.ZERO;
                BigDecimal bankSubsidy = BigDecimal.ZERO;
                BigDecimal mchntSubsidy = BigDecimal.ZERO;

                /* 计算总优惠金额 */
                for (SubsidyAmount subsidyAmount : subsidyAmountList) {
                    totalSubsidy = totalSubsidy.add(subsidyAmount.getTotalSubsidy());
                    bankSubsidy = bankSubsidy.add(subsidyAmount.getBankSubsidy());
                    mchntSubsidy = mchntSubsidy.add(subsidyAmount.getMchntSubsidy());
                }

                rglog.debug("TOTAL_SUBSIDY=<{}>, BANK_SUBSIDY=<{}>, MCHNT_SUBSIDY=<{}>", totalSubsidy.toString(), bankSubsidy.toString(), mchntSubsidy.toString());

                comboPaymentResponse.setTxnAmt(orderAmt.subtract(totalSubsidy).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
                comboPaymentResponse.setTotalSubsidy(totalSubsidy.toString());
                comboPaymentResponse.setBankSubsidy(bankSubsidy.toString());
                comboPaymentResponse.setMchntSubsidy(mchntSubsidy.toString());

                tmTxnOrder.setTxnAmt(comboPaymentResponse.getTxnAmt());
                tmTxnOrder.setSubsidyAmt(totalSubsidy.toString());
                tmTxnOrder.setBankSubsidyAmt(bankSubsidy.toString());
                tmTxnOrder.setMchntSubsidyAmt(mchntSubsidy.toString());

                rglog.info("********************************减免类共优惠<{}>, 其中银行分摊<{}>, 商户分摊<{}>********************************", totalSubsidy.toString(), bankSubsidy.toString(), mchntSubsidy.toString());
            }
        }

        /* 卡券和减免的优惠金额整合 */
        if (mcCouponTxnData != null) {
            if (!StringUtil.isNullorEmpty(mcCouponTxnData.getTotalSubsidy())) {

                BigDecimal txnAmt = new BigDecimal(tmTxnOrder.getTxnAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal totalSubsidy = new BigDecimal(mcCouponTxnData.getTotalSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal bankSubsidy = new BigDecimal(mcCouponTxnData.getBankSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal mchntSubsidy = new BigDecimal(mcCouponTxnData.getMchntSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                txnAmt = txnAmt.subtract(totalSubsidy).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                totalSubsidy = totalSubsidy.add(new BigDecimal(tmTxnOrder.getSubsidyAmt())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                bankSubsidy = bankSubsidy.add(new BigDecimal(tmTxnOrder.getBankSubsidyAmt())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                mchntSubsidy = mchntSubsidy.add(new BigDecimal(tmTxnOrder.getMchntSubsidyAmt())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                rglog.info("********************************对客类共优惠<{}>, 其中银行分摊<{}>, 商户分摊<{}>********************************", totalSubsidy.toString(), bankSubsidy.toString(), mchntSubsidy.toString());

                comboPaymentResponse.setTxnAmt(txnAmt.toString());
                comboPaymentResponse.setTotalSubsidy(totalSubsidy.toString());
                comboPaymentResponse.setBankSubsidy(bankSubsidy.toString());
                comboPaymentResponse.setMchntSubsidy(mchntSubsidy.toString());

                tmTxnOrder.setTxnAmt(txnAmt.toString());
                tmTxnOrder.setSubsidyAmt(totalSubsidy.toString());
                tmTxnOrder.setBankSubsidyAmt(bankSubsidy.toString());
                tmTxnOrder.setMchntSubsidyAmt(mchntSubsidy.toString());
            }
        }

        /*
         *  商户手续费优惠计算时:
         *      若无优惠信息,该商户手续费优惠金额为0,业务处理成功
         *      若有优惠信息,但该商户手续费计算失败(数据库操作异常等问题),所有已优惠信息统统失败
         *  */
        rglog.info("=========================================对客部分处理完毕,开始处理手续费优惠部分=========================================");
//        dbsUtil.dbsBeginTransaction();
        returnCode = processMchntFeeDiscountProcedure(comboPaymentRequest);
        if (returnCode != CommonConstant.PROCESS_SUCCESS) {

            rglog.info("********************************商户手续费优惠部分业务处理失败,全订单失败所有数据回滚,登记失败订单信息********************************");

            /* 整个合并支付订单处理失败,回滚所有数据库操作 */
            dbsUtil.dbsEndTransaction(false);
            rglog.error("{}, TRACE_NO=<{}>, RETURN_CODE=<{}>", RespCodeEnum.FAILED_TO_DISCOUNT_FOR_MDF_MC_ERROR.getRespDesc(), globalTraceNo, returnCode);

            /* 确保任何情况下订单流水表都有记录存在 */
            procNormalStatus = false;
            onlyRecordTxnOrderInfo(xmlTreeUtil);

            comboPaymentResponse.setTxnAmt(comboPaymentRequest.getTransAmt());
            comboPaymentResponse.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
            comboPaymentResponse.setBankSubsidy(CommonConstant.ZERO_AMOUNT);
            comboPaymentResponse.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);

            bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
            bizResponse.setRespCode(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_MDF_MC_ERROR.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_MDF_MC_ERROR.getRespDesc());
            xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, RespCodeEnum.FAILED_TO_DISCOUNT_FOR_MDF_MC_ERROR.getRespDesc());

            comboPaymentResponse.setRespCode(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_MDF_MC_ERROR.getRespCode());
            comboPaymentResponse.setRespDesc(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_MDF_MC_ERROR.getRespDesc());

            bizResponse.setResult(comboPaymentResponse);

            return bizResponse;
        }

        rglog.info("=========================================所有业务处理完毕,开始处理数据库操作=========================================");

        /* 根据业务处理流程判断提交事务或回滚事务 */
        returnCode = databaseOperation();
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("数据库操作失败，回滚所有数据！");
            /* 回滚数据库事务并交易失败 */
            dbsUtil.dbsEndTransaction(false);

            /* 确保任何情况下订单流水表都有记录存在 */
            procNormalStatus = false;
            onlyRecordTxnOrderInfo(xmlTreeUtil);

            comboPaymentResponse.setTxnAmt(comboPaymentRequest.getTransAmt());
            comboPaymentResponse.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
            comboPaymentResponse.setBankSubsidy(CommonConstant.ZERO_AMOUNT);
            comboPaymentResponse.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);

            bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
            bizResponse.setRespCode(RespCodeEnum.SYSTEM_ERROR.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.SYSTEM_ERROR.getRespDesc());

            comboPaymentResponse.setRespCode(RespCodeEnum.SYSTEM_ERROR.getRespCode());
            comboPaymentResponse.setRespDesc(RespCodeEnum.SYSTEM_ERROR.getRespDesc());

        } else {
            /* 提交数据库事务并交易成功 */
            dbsUtil.dbsEndTransaction(true);

            comboPaymentResponse.setOrderDetailList(paymentOrderDetailBeanList);

            bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
            bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

            comboPaymentResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            comboPaymentResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        }


        bizResponse.setResult(comboPaymentResponse);

        return bizResponse;
    }

    /**
     * 卡券业务处理分支
     * <p>
     * 本次仅支持处理1张卡券的流程
     *
     * @param comboPaymentRequest (合并)支付接口请求对象
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/9 13:59
     */
    private int processCouponProcedure(ComboPaymentRequest comboPaymentRequest) {

        rglog.info("开始处理卡券核销子流程");

        try {
            //如果未上送userId ，卡券和减免不享受优惠
            if (userIdFlag.equals(CommonConstant.ONE_COMMON_CONSTANT)) {
                rglog.info("未上送userId，不享受卡券和减免优惠");
                mcCouponTxnData = null;
                return CommonConstant.PROCESS_FAILED;
            }

            /* 未上送卡券信息 */
            if (null == comboPaymentRequest.getCouponInfoList() || comboPaymentRequest.getCouponInfoList().isEmpty()) {
                rglog.info("法人机构<{}>流水号<{}>订单号<{}>未上送卡券信息,卡券核销子流程处理成功!", globalInstId, globalTraceNo, globalOrderId);
                mcCouponTxnData = null;
                return CommonConstant.PROCESS_SUCCESS;
            }

            /* 判断接口上送卡券数量 */
            List<PaymentOrderCouponInfoBean> paymentOrderCouponInfoBeanList = comboPaymentRequest.getCouponInfoList();
            if (CommonConstant.ONE != paymentOrderCouponInfoBeanList.size()) {
                rglog.info("法人机构<{}>的流水号<{}>,商户订单号<{}>的合并支付交易上送超过了1张卡券,卡券不处理,卡券核销子流程处理失败!", globalInstId, globalTraceNo, globalOrderId);
                mcCouponTxnData = null;
                return CommonConstant.PROCESS_FAILED;
            }

            /* 卡券信息内外报文转换,目前只处理单条卡券信息 */
            mcCouponTxnData = new McCouponTxnData();
            convertCouponInfoFromRequest(comboPaymentRequest, mcCouponTxnData);

            /* 商户订单明细内外报文转换 */
            List<McMchntOrderData> mcMchntOrderDataList = new ArrayList<>();
            comboPaymentRequest.getOrderDetailList().forEach(item -> convertMcMchntOrderInfoFromRequest(item, comboPaymentRequest, mcMchntOrderDataList));

            /* 判断数据有效性 */
            if (mcMchntOrderDataList.isEmpty()) {
                /* 接口里无数据 */
                rglog.info("{}, INST_ID=<{}>, TRACE_NO=<{}>", RespCodeEnum.NO_AVAILABLE_DATA_TO_PROCESS_ERROR.getRespDesc(), globalInstId, globalTraceNo);
                mcCouponTxnData = null;
                return CommonConstant.PROCESS_FAILED;
            }

            /* 计算卡券优惠情况 */
            calCouponDiscount(mcCouponTxnData, mcMchntOrderDataList);

        } catch (Exception e) {
            rglog.error("处理卡券类营销活动流程发生异常,不可进行卡券和减免类优惠! 异常信息:<{}>", StringUtil.ExceptionToString(e));
            mcCouponTxnData = null;
            return CommonConstant.PROCESS_FAILED;
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 卡券核销
     *
     * @param mcCouponTxnData      (合并)支付使用卡券类交易信息
     * @param mcMchntOrderDataList 营销活动商户订单明细实体类
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/18 11:10
     */
    private void calCouponDiscount(McCouponTxnData mcCouponTxnData, List<McMchntOrderData> mcMchntOrderDataList) throws Exception {

        String couponNo = mcCouponTxnData.getCouponNo();

        /* 获取卡券基本信息 */
        TMCouponInfo tmCouponInfo = new TMCouponInfo();
        tmCouponInfo.setInstId(globalInstId);
        tmCouponInfo.setCouponNo(couponNo);

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        tmCouponInfo = couponInfoMapper.selectSingleCouponInfoByCouponNo(tmCouponInfo);
        if (null == tmCouponInfo) {
            rglog.error("机构<{}>卡券编号<{}>获取卡券信息失败!不可进行卡券和减免类优惠!", globalInstId, couponNo);
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }

        /* 判断卡券状态是否可核销 */
        int returnCode = checkCouponStatus(tmCouponInfo);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("机构<{}>卡券编号<{}>卡券!不可进行卡券和减免类优惠!", globalInstId, couponNo);
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }
        convertCouponInfo(tmCouponInfo, mcCouponTxnData);

        String mcNo = tmCouponInfo.getMcNo();
        rglog.debug("MC_NO=<{}>", mcNo);

        /* 获取营销活动信息 */
        TMMcCouponInfo tmMcCouponInfo = selectCouponMcInfoByPrimaryKey(globalInstId, mcNo);
        if (null == tmMcCouponInfo) {
            rglog.error("获取法人机构<{}>的卡券编号<{}>的卡券营销活动<{}>的基本信息失败! 不可进行卡券和减免类优惠!", globalInstId, couponNo, mcNo);
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }
        //优惠所用id
        convertCouponMcInfo(tmMcCouponInfo, mcCouponTxnData);

        //查询该用户，活动下的营销用户信息表信息 目前只支持减免类活动卡bin 卡产品
        List<TMMcUserInfo> userInfoList = checkUserInfo(globalInstId, mcNo, discountId);
        //没有配置手机号 银行卡号 卡bin，查询有没有配置卡产品
        if (null == userInfoList || userInfoList.size() == 0) {
            if (mcCouponTxnData.getUserId().length() >= 10) {
                McUserInfoMapper mcUserInfoMapper = new McUserInfoMapperImpl();
                userInfoList = mcUserInfoMapper.selectMcUserInfoListByInstIdMcNoAcctNo(globalInstId, mcNo, discountId.substring(0, 10));
            }
        }
        //测试账户
        List<TMMcUserInfo> testUserInfoList = new ArrayList<>();
        //正式账户
        List<TMMcUserInfo> formalUserInfoList = new ArrayList<>();
        if (null != userInfoList && userInfoList.size() > 0) {
            testUserInfoList = userInfoList.stream().filter(item -> item.getAcctFlag().equals(CommonConstant.ACCT_FLAG_TESTING)).collect(Collectors.toList());
            formalUserInfoList = userInfoList.stream().filter(item -> item.getAcctFlag().equals(CommonConstant.ACCT_FLAG_NORMAL)).collect(Collectors.toList());
        }
        /* 判断用户是否在营销活动允许的用户范围内-无需记录对应的用户规则 */
        if (CommonConstant.ALL_CLIENT_SUPPORT.equals(tmMcCouponInfo.getClientRange())) {
            rglog.info("机构<{}>的营销活动<{}>支持对所有用户减免,继续校验后续信息!", globalInstId, mcNo);
            if (tmMcCouponInfo.getMcStatus().equals(McStatusEnum.TESTING.getMcStatusCode()) && testUserInfoList.size() == 0) {
                rglog.info("获取机构<{}>的营销活动<{}>用户信息匹配失败,本营销活动不予优惠!", globalInstId, mcNo);
                throw new BizException(RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespCode(), RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespDesc());
            }

            //判断用户参与活动次数是否超过活动配置的限制次数——不限定用户
            Boolean userAttendIsReachLimit = checkIsUserReachLimit(tmMcCouponInfo, null);
            if (!userAttendIsReachLimit) {
                rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数大于等于最大限制，卡券无法使用！", discountId, mcNo);
                throw new BizException(RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespCode(), RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespDesc());
            }
        } else if (CommonConstant.SPECIFIC_CLIENT_SUPPORT.equals(tmMcCouponInfo.getClientRange())) {
            rglog.info("机构<{}>的营销活动<{}>支持对部分用户减免,需要进一步判断当前用!", globalInstId, mcNo);
            ;
            if (formalUserInfoList.size() > 0 && tmMcCouponInfo.getMcStatus().equals(McStatusEnum.PROGRESSING.getMcStatusCode())) {
                rglog.info("获取机构<{}>的营销活动<{}>用户信息匹配成功,继续校验后续信息!", globalInstId, mcNo);
                //判断用户参与活动次数是否超过活动配置的限制次数——正式用户
                Boolean userAttendIsReachLimit = checkIsUserReachLimit(tmMcCouponInfo, formalUserInfoList);
                if (!userAttendIsReachLimit) {
                    rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数大于等于最大限制，卡券无法使用！", discountId, mcNo);
                    throw new BizException(RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespCode(), RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespDesc());
                }
            } else if (testUserInfoList.size() > 0 && tmMcCouponInfo.getMcStatus().equals(McStatusEnum.TESTING.getMcStatusCode())) {
                rglog.info("获取机构<{}>的营销活动<{}>用户信息匹配成功,继续校验后续信息!", globalInstId, mcNo);
                //判断用户参与活动次数是否超过活动配置的限制次数——测试用户
                Boolean userAttendIsReachLimit = checkIsUserReachLimit(tmMcCouponInfo, testUserInfoList);
                if (!userAttendIsReachLimit) {
                    rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数大于等于最大限制，卡券无法使用！", discountId, mcNo);
                    throw new BizException(RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespCode(), RespCodeEnum.COUPON_PROCESS_FAILED_ERROR.getRespDesc());
                }
            } else {
                rglog.info("获取机构<{}>的营销活动<{}>用户信息匹配失败,本营销活动不予优惠!", globalInstId, mcNo);
                throw new BizException(RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespCode(), RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespDesc());

            }
        } else {
            rglog.error("机构<{}>的营销活动<{}>客户范围<{}>异常,本营销活动不予优惠!", globalInstId, mcNo, tmMcCouponInfo.getClientRange());
            throw new BizException(RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespCode(), RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespDesc());

        }
        /* 判断是否在营销活动允许的时间范围内-无需记录对应的时间规则 */
        if (CommonConstant.ALL_TIME_SUPPORT.equals(tmMcCouponInfo.getMcTimeFlag())) {
            rglog.info("机构<{}>的营销活动<{}>在任意时间段内可用!继续校验后续信息!", globalInstId, mcNo);
        } else if (CommonConstant.SPECIFIC_TIME_SUPPORT.equals(tmMcCouponInfo.getMcTimeFlag())) {
            rglog.info("机构<{}>的营销活动<{}>在指定时间段内可用,需要进一步判断当前时间!", globalInstId, mcNo);
            List<TMMcTimeInfo> tmMcTimeInfoList = getAllMcTimeListInfo(globalInstId, mcNo);
            if (null == tmMcTimeInfoList || tmMcTimeInfoList.isEmpty()) {
                rglog.info("获取机构<{}>的营销活动<{}>时间规则信息失败,本营销活动不予优惠!", globalInstId, mcNo);
                throw new BizException(RespCodeEnum.GET_MC_TIME_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_TIME_INFO_ERROR.getRespDesc());
            } else {
                int retCode = checkMcTimeInfo(mcCouponTxnData.getTransDate(), mcCouponTxnData.getTransTime(), tmMcTimeInfoList);
                if (CommonConstant.PROCESS_SUCCESS != retCode) {
                    rglog.info("获取机构<{}>的营销活动<{}>时间规则信息匹配失败,本营销活动不予优惠!", globalInstId, mcNo);
                    throw new BizException(RespCodeEnum.NOT_IN_THE_AVAILABLE_TIME_PERIOD.getRespCode(), RespCodeEnum.NOT_IN_THE_AVAILABLE_TIME_PERIOD.getRespDesc());
                } else {
                    rglog.info("获取机构<{}>的营销活动<{}>时间规则信息匹配成功,继续校验后续信息!", globalInstId, mcNo);
                }
            }
        } else {
            rglog.error("机构<{}>的营销活动<{}>活动时间标志<{}>异常,本营销活动不予优惠!", globalInstId, mcNo, tmMcCouponInfo.getMcTimeFlag());
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }

        /* 使用卡券面额过滤商户订单信息,只有订单金额大于等于卡券面额的商户列表可以进一步处理 */
        BigDecimal criteria = new BigDecimal(tmCouponInfo.getCriteria()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        List<McMchntOrderData> mcMchntOrderDataList1 = mcMchntOrderDataList.stream().filter(item -> (CommonConstant.ZERO <= item.getOrderAmtNum().compareTo(criteria))).collect(Collectors.toList());
        if (mcMchntOrderDataList1.isEmpty()) {
            rglog.error("机构<{}>卡券编号<{}>的面额<{}>的使用门槛<{}>超过合并支付订单中所有子订单的订单金额!不可进行卡券和减免类优惠!",
                    globalInstId, couponNo, tmCouponInfo.getCouponAmt(), criteria.toString());
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }

        /* 匹配使用卡券的子订单 */
        McMchntOrderData mcMchntOrderData = matchMchntForCouponMc(mcNo, mcMchntOrderDataList1);
        if (null == mcMchntOrderData) {
            rglog.error("机构<{}>卡券编号<{}>未取到指定卡券的营销活动匹配的商户数据!不可进行卡券和减免类优惠!", globalInstId, couponNo);
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }

        /* 赋值订单金额和商户号 */
        mcCouponTxnData.setMchntNo(mcMchntOrderData.getMchntNo());
        mcCouponTxnData.setOrderAmt(mcMchntOrderData.getOrderAmt());

        /* 计算卡券优惠各金额 */
        calCouponDiscountInfo(mcCouponTxnData);
        if (CommonConstant.ZERO_AMOUNT.equals(mcCouponTxnData.getTotalSubsidy())) {
            rglog.error("机构<{}>的卡券营销活动的卡券编号<{}>的优惠数据计算失败!不可进行卡券和减免类优惠!", globalInstId, mcNo, couponNo);
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }

        /* 额度更新数据准备 */
        convertMcLimitDetail(mcCouponTxnData);

        /* 订单明细更新数据准备 */
        convertTxnOrderDetail(mcCouponTxnData);

        //卡券信息赋值
        this.tmCouponInfo = tmCouponInfo;
    }

    /**
     * 满减更新各维度额度数据准备
     *
     * @param object (合并)支付使用交易信息
     * @author Jinan Liu
     * @since 2020/6/5 17:30
     */
    private void convertMcLimitDetail(Object object) {

        String instId;
        String mcNo;
        String mchntNo;
        String ruleIndex;
        String totalSubsidy;
        String bankSubsidy = null;
        String mchntSubsidy = null;
        String orderAmt = null;

        if (object instanceof McMoneyOffTxnData) {
            instId = ((McMoneyOffTxnData) object).getInstId();
            mcNo = ((McMoneyOffTxnData) object).getMcNo();
            mchntNo = ((McMoneyOffTxnData) object).getMchntNo();
            ruleIndex = ((McMoneyOffTxnData) object).getRuleIndex();
            totalSubsidy = ((McMoneyOffTxnData) object).getTotalSubsidy();
            bankSubsidy = ((McMoneyOffTxnData) object).getBankSubsidy();
            mchntSubsidy = ((McMoneyOffTxnData) object).getMchntSubsidy();
            orderAmt = ((McMoneyOffTxnData) object).getOrderAmt();
        } else if (object instanceof McMchntFeeDiscountTxnData) {
            instId = ((McMchntFeeDiscountTxnData) object).getInstId();
            mcNo = ((McMchntFeeDiscountTxnData) object).getMcNo();
            mchntNo = ((McMchntFeeDiscountTxnData) object).getMchntNo();
            ruleIndex = ((McMchntFeeDiscountTxnData) object).getRuleIndex();
            totalSubsidy = ((McMchntFeeDiscountTxnData) object).getMchntFeeDiscount();
            orderAmt = ((McMchntFeeDiscountTxnData) object).getMchntFeeDiscountTransAmt();

        } else if (object instanceof McCouponTxnData) {
            instId = ((McCouponTxnData) object).getInstId();
            mcNo = ((McCouponTxnData) object).getMcNo();
            mchntNo = ((McCouponTxnData) object).getMchntNo();
            ruleIndex = ((McCouponTxnData) object).getRuleIndex();
            totalSubsidy = ((McCouponTxnData) object).getTotalSubsidy();
            bankSubsidy = ((McCouponTxnData) object).getBankSubsidy();
            mchntSubsidy = ((McCouponTxnData) object).getMchntSubsidy();
            orderAmt = ((McCouponTxnData) object).getOrderAmt();
        } else {
            return;
        }

        if (object instanceof McMchntFeeDiscountTxnData) {

            /* 商户手续费优惠部分流程 */

            /* 手续费减免活动单日统计表 */
            TMStatMfdDay tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setInstId(instId);
            tmStatMfdDay.setTxnDate(globalTxnDate);
            tmStatMfdDay.setMcNo(mcNo);
            tmStatMfdDay.setRuleIndex(ruleIndex);
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(totalSubsidy);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(orderAmt);
            tmStatMfdDay.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay.setPaidAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay.setCreateTime(globalTimeStamp);
            tmStatMfdDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay.setUpdateTime(globalTimeStamp);
            tmStatMfdDayList.add(tmStatMfdDay);

            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDay tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setInstId(instId);
            tmStatMfdMchntDay.setTxnDate(globalTxnDate);
            tmStatMfdMchntDay.setMcNo(mcNo);
            tmStatMfdMchntDay.setMchntNo(mchntNo);
            tmStatMfdMchntDay.setRuleIndex(ruleIndex);
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(totalSubsidy);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(orderAmt);
            tmStatMfdMchntDay.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay.setCreateTime(globalTimeStamp);
            tmStatMfdMchntDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay.setUpdateTime(globalTimeStamp);
            tmStatMfdMchntDayList.add(tmStatMfdMchntDay);

        } else {

            /* 对客部分流程 */
            rglog.debug("对客类统计数据准备");

            /* 对客户营销活动单日统计表数据 */
            TMStat2CDay tmStat2CDay = new TMStat2CDay();
            tmStat2CDay.setInstId(instId);
            tmStat2CDay.setTxnDate(globalTxnDate);
            tmStat2CDay.setMcNo(mcNo);
            tmStat2CDay.setRuleIndex(ruleIndex);
            tmStat2CDay.setTotalAmtAcc(totalSubsidy);
            tmStat2CDay.setTxnQtyAcc(orderAmt);
            tmStat2CDay.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            if (!CommonConstant.ZERO_AMOUNT.equals(bankSubsidy)) {
                tmStat2CDay.setBankAmtAcc(bankSubsidy);
                tmStat2CDay.setBankQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                tmStat2CDay.setBankAmtAcc(CommonConstant.ZERO_AMOUNT);
                tmStat2CDay.setBankQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            if (!CommonConstant.ZERO_AMOUNT.equals(mchntSubsidy)) {
                tmStat2CDay.setMchntAmtAcc(mchntSubsidy);
                tmStat2CDay.setMchntQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                tmStat2CDay.setMchntAmtAcc(CommonConstant.ZERO_AMOUNT);
                tmStat2CDay.setMchntQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStat2CDay.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay.setAvgTotalAmt(CommonConstant.ZERO_AMOUNT);
            tmStat2CDay.setAvgBankAmt(CommonConstant.ZERO_AMOUNT);
            tmStat2CDay.setAvgMchntAmt(CommonConstant.ZERO_AMOUNT);
            tmStat2CDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CDay.setCreateTime(globalTimeStamp);
            tmStat2CDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CDay.setUpdateTime(globalTimeStamp);
            tmStat2CDayList.add(tmStat2CDay);

            /* 更新对客户营销活动商户单日统计表的数据 */
            BigDecimal zero = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal mchntSubsidyAmt = new BigDecimal(mchntSubsidy).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal bankSubsidyAmt = new BigDecimal(bankSubsidy).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 对客户营销活动商户统计表数据 */
            TMStat2CMchntDay tmStat2CMchntDay = new TMStat2CMchntDay();
            tmStat2CMchntDay.setInstId(instId);
            tmStat2CMchntDay.setTxnDate(globalTxnDate);
            tmStat2CMchntDay.setMcNo(mcNo);
            tmStat2CMchntDay.setMchntNo(mchntNo);
            tmStat2CMchntDay.setTotalAmtAcc(mchntSubsidy);
            if (mchntSubsidyAmt.compareTo(zero) > CommonConstant.ZERO)
                tmStat2CMchntDay.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            else
                tmStat2CMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CMchntDay.setAvgAmtAcc(CommonConstant.ZERO_AMOUNT);

            tmStat2CMchntDay.setBankAmtAcc(bankSubsidy);
            if (bankSubsidyAmt.compareTo(zero) > CommonConstant.ZERO)
                tmStat2CMchntDay.setBankQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            else
                tmStat2CMchntDay.setBankQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CMchntDay.setAvgBankAmtAcc(CommonConstant.ZERO_AMOUNT);
            tmStat2CMchntDay.setTxnAmtAcc(orderAmt);
            tmStat2CMchntDay.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CMchntDay.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CMchntDay.setCreateTime(globalTimeStamp);
            tmStat2CMchntDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CMchntDay.setUpdateTime(globalTimeStamp);
            tmStat2CMchntDayList.add(tmStat2CMchntDay);
        }
    }

    /**
     * 订单明细记录数据准备
     *
     * @param object 营销活动交易信息数据对象
     * @author Jinan Liu
     * @since 2020/6/4 19:22
     */
    private void convertTxnOrderDetail(Object object) {

        TMTxnOrderDet tmTxnOrderDet = new TMTxnOrderDet();

        if (object instanceof McMoneyOffTxnData) {

            /* 满减订单明细数据准备 */
            McMoneyOffTxnData mcMoneyOffTxnData = (McMoneyOffTxnData) object;

            tmTxnOrderDet.setInstId(globalInstId);
            tmTxnOrderDet.setTxnDate(globalTxnDate);
            tmTxnOrderDet.setFrontSeqNum(globalTraceNo);
            tmTxnOrderDet.setOrderId(globalOrderId);
            tmTxnOrderDet.setMchntNo(mcMoneyOffTxnData.getMchntNo());
            tmTxnOrderDet.setUserId(discountId);
            tmTxnOrderDet.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            tmTxnOrderDet.setMcType(mcMoneyOffTxnData.getMcType());
            tmTxnOrderDet.setOriginalAmt(mcMoneyOffTxnData.getOrderAmt());
            tmTxnOrderDet.setMcNo(mcMoneyOffTxnData.getMcNo());
            tmTxnOrderDet.setRuleIndex(mcMoneyOffTxnData.getRuleIndex());

            String subsidy = new BigDecimal(mcMoneyOffTxnData.getTotalSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
            tmTxnOrderDet.setSubsidy(subsidy);
            String bankSubsidy = new BigDecimal(mcMoneyOffTxnData.getBankSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
            tmTxnOrderDet.setBankSubsidy(bankSubsidy);

            tmTxnOrderDet.setMchntSubsidy(mcMoneyOffTxnData.getMchntSubsidy());
            tmTxnOrderDet.setRelativeData("{}");
            tmTxnOrderDet.setOrderRemark("{}");
            tmTxnOrderDet.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmTxnOrderDet.setCreateTime(globalTimeStamp);

        } else if (object instanceof McMchntFeeDiscountTxnData) {

            /* 手续费优惠订单明细数据准备 */
            McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData = (McMchntFeeDiscountTxnData) object;

            tmTxnOrderDet.setInstId(globalInstId);
            tmTxnOrderDet.setTxnDate(globalTxnDate);
            tmTxnOrderDet.setFrontSeqNum(globalTraceNo);
            tmTxnOrderDet.setOrderId(globalOrderId);
            tmTxnOrderDet.setMchntNo(mcMchntFeeDiscountTxnData.getMchntNo());
            tmTxnOrderDet.setUserId(discountId);
            tmTxnOrderDet.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            tmTxnOrderDet.setMcType(mcMchntFeeDiscountTxnData.getMcType());
            tmTxnOrderDet.setOriginalAmt(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
            tmTxnOrderDet.setMcNo(mcMchntFeeDiscountTxnData.getMcNo());
            tmTxnOrderDet.setRuleIndex(mcMchntFeeDiscountTxnData.getRuleIndex());
            tmTxnOrderDet.setSubsidy(mcMchntFeeDiscountTxnData.getMchntFeeDiscount());
            tmTxnOrderDet.setBankSubsidy(mcMchntFeeDiscountTxnData.getMchntFeeDiscount());
            tmTxnOrderDet.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);
            String orderRemark = JsonOperation.packMfdMcOrderDetailOrderRemark((McMchntFeeDiscountTxnData) object, rglog);
            tmTxnOrderDet.setRelativeData(orderRemark);
            tmTxnOrderDet.setOrderRemark(orderRemark);
            tmTxnOrderDet.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmTxnOrderDet.setCreateTime(globalTimeStamp);
            //商户优惠交易金额
            tmTxnOrderDet.setDisTxAmt(mcMchntFeeDiscountTxnData.getMchntFeeDiscountTransAmt());

        } else if (object instanceof McCouponTxnData) {

            McCouponTxnData mcCouponTxnData = (McCouponTxnData) object;

            tmTxnOrderDet.setInstId(globalInstId);
            tmTxnOrderDet.setTxnDate(globalTxnDate);
            tmTxnOrderDet.setFrontSeqNum(globalTraceNo);
            tmTxnOrderDet.setOrderId(globalOrderId);
            tmTxnOrderDet.setMchntNo(mcCouponTxnData.getMchntNo());
            tmTxnOrderDet.setUserId(discountId);
            tmTxnOrderDet.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            tmTxnOrderDet.setMcType(mcCouponTxnData.getMcType());
            tmTxnOrderDet.setOriginalAmt(mcCouponTxnData.getOrderAmt());
            tmTxnOrderDet.setMcNo(mcCouponTxnData.getMcNo());
            tmTxnOrderDet.setRuleIndex(mcCouponTxnData.getRuleIndex());
            tmTxnOrderDet.setSubsidy(mcCouponTxnData.getTotalSubsidy());
            tmTxnOrderDet.setBankSubsidy(mcCouponTxnData.getBankSubsidy());
            tmTxnOrderDet.setMchntSubsidy(mcCouponTxnData.getMchntSubsidy());
            String orderRemark = JsonOperation.packCpMcOrderDetailOrderRemark(mcCouponTxnData, rglog);
            tmTxnOrderDet.setRelativeData(orderRemark);
            tmTxnOrderDet.setOrderRemark(orderRemark);
            tmTxnOrderDet.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmTxnOrderDet.setCreateTime(globalTimeStamp);
        } else {
            rglog.error("错误的参数类型! CLASS=><{}>", object.getClass());
            return;
        }

        tmTxnOrderDetList.add(tmTxnOrderDet);
    }

    /**
     * 匹配商户订单明细和卡券营销活动商户信息
     *
     * @param mcNo               营销活动编号
     * @param mchntOrderDataList 营销活动商户订单明细实体类
     * @return cc.rengu.igas.momp.common.entity.McMchntOrderData
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/18 18:02
     */
    private McMchntOrderData matchMchntForCouponMc(String mcNo, List<McMchntOrderData> mchntOrderDataList) throws Exception {

        List<McMchntOrderData> mcMchntOrderDataList = new ArrayList<>();

        /* 取商户订单明细中商圈信息 */
        for (McMchntOrderData mcMchntOrderData : mchntOrderDataList) {

            mcMchntOrderData.setMcNo(mcNo);

            /* 判断订单明细中哪些商户参加了卡券编号对应的卡券营销活动 */
            String mchntNo = mcMchntOrderData.getMchntNo();
            TBMchntBaseInfo tbMchntBaseInfo = tbMchntBaseInfoList.stream().filter(object -> object.getMchntNo().equals(mchntNo)).collect(Collectors.toList()).get(CommonConstant.ZERO);

            /* 判断商户是否出现在订单列表中 */
            McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
            if (!StringUtil.isNullorEmpty(tbMchntBaseInfo.getMchntArea())) {
                mcMchntOrderData.setMchntArea(tbMchntBaseInfo.getMchntArea());
            }

            /* 查询商户是否参与了指定的卡券营销活动 */
            TMMcMchntInfo tmMcMchntInfo = mcMchntInfoMapper.matchCpMcInfoByMchntNoAndMchntArea(mcMchntOrderData);
            if (null == tmMcMchntInfo) {
                rglog.info("法人机构<{}>的商户<{}>未参加卡券营销活动<{}>!", globalInstId, mchntNo, mcNo);
                continue;
            } else {
                if (!tmMcMchntInfo.getExitFlag().equals(CommonConstant.MC_NOT_EXIT_FLAG) && !tmMcMchntInfo.getNewMchntFlag().equals(CommonConstant.MCHNT_OLD_FLAG)) {
                    rglog.info("法人机构<{}>的商户<{}>未参加卡券营销活动<{}>!NEW_MCHNT_FLAG<{}>,EXIT_FLAG<{}>", globalInstId, mchntNo, mcNo, tmMcMchntInfo.getNewMchntFlag(), tmMcMchntInfo.getExitFlag());
                    continue;
                }
            }

            mcMchntOrderDataList.add(mcMchntOrderData);
        }

        if (mcMchntOrderDataList.isEmpty()) {
            /* 所有商户均未参加营销活动,不可优惠 */
            rglog.info("法人机构号<{}>的流水号<{}>的所有商户均未参加卡券营销活动<{}>,不可优惠!", globalInstId, globalTraceNo, mcNo);
            return null;
        } else {
            /* 有至少一个商户参加了营销活动,选取订单金额最大的进行优惠 */
            return mcMchntOrderDataList.stream().max(Comparator.comparing(McMchntOrderData::getOrderAmtNum)).get();
        }
    }

    /**
     * 计算卡券优惠各金额
     *
     * @param mcCouponTxnData (合并)支付使用卡券类交易信息
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/18 22:49
     */
    private void calCouponDiscountInfo(McCouponTxnData mcCouponTxnData) throws Exception {

        String mcNo = mcCouponTxnData.getMcNo();
        String mcType = mcCouponTxnData.getMcType();

        /* 取营销活动规则 */
        Object object = getMatchedMcRuleInfo(globalInstId, mcNo, mcCouponTxnData.getRuleIndex(), mcCouponTxnData.getMcType());
        if (null == object) {
            /* 未取到营销活动规则信息,本营销活动不可以优惠! */
            rglog.info("获取机构<{}>的营销活动<{}>卡券类营销活动规则信息匹配失败,本营销活动不予优惠!", globalInstId, mcNo);
            mcCouponTxnData.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
            return;
        } else {
            mcCouponTxnData.setQuantity(((TMMcCouponRuleInfo) object).getQuantity());
            mcCouponTxnData.setDayRedeemLimit(((TMMcCouponRuleInfo) object).getDayRedeemLimit());
        }

        /* 判断订单金额必须大于卡券面额,否则不优惠 */
        BigDecimal orderAmt = new BigDecimal(mcCouponTxnData.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal couponAmt = new BigDecimal(mcCouponTxnData.getCouponAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        if (CommonConstant.ZERO >= orderAmt.compareTo(couponAmt)) {
            rglog.error("当前订单金额为<{}>,卡券面额为<{}>,订单金额小于等于卡券面额,不可优惠!", mcCouponTxnData.getOrderAmt(), mcCouponTxnData.getCouponAmt());
            mcCouponTxnData.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
            return;
        }

        /* 卡券类营销活动总补贴金额无需计算,直接使用卡券面额 */
        String subsidy = mcCouponTxnData.getCouponAmt();
        if (null == subsidy) {
            rglog.error("机构<{}>的营销活动<{}>卡券减免金额计算失败,本营销活动不予优惠!", globalInstId, mcNo);
            mcCouponTxnData.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
            return;
        } else {
            rglog.info("TOTAL_SUBSIDY=<{}>, COUPON_AMT=<{}>", subsidy, mcCouponTxnData.getCouponAmt());
            mcCouponTxnData.setTotalSubsidy(subsidy);
        }

        /* 判断银行和商户出资方式 */
        McSubsidyData mcSubsidyData = new McSubsidyData();
        mcSubsidyData.setTotalSubsidy(subsidy);
        mcSubsidyData.setSponsor(mcCouponTxnData.getSponsor());
        if (CommonConstant.SPONSOR_MIXED.equals(mcCouponTxnData.getSponsor())) {
            mcSubsidyData.setBudget(mcCouponTxnData.getBudget());
            mcSubsidyData.setBankBudget(mcCouponTxnData.getBankBudget());
            mcSubsidyData.setExpectMchntQty(mcCouponTxnData.getExpectMchntQty());
            mcSubsidyData.setBankBudgetRatio(mcCouponTxnData.getBankBudgetRatio());
        }
        mcSubsidyData.setMcType(mcType);

        /* 计算银行和商户营销资金出资金额 */
        int returnCode = calculateBankAndMchntSubsidyRatio(mcSubsidyData);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.info("机构<{}>的营销活动<{}>计算银行补贴金额和商户补贴金额失败,本营销活动不予优惠!", globalInstId, mcNo);
            mcCouponTxnData.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
            return;
        }

        /* 根据计算结果赋值银行补贴及商户补贴金额 */
        mcCouponTxnData.setBankSubsidy(mcSubsidyData.getBankSubsidy());
        mcCouponTxnData.setMchntSubsidy(mcSubsidyData.getMchntSubsidy());
        if (CommonConstant.SPONSOR_MIXED.equals(mcCouponTxnData.getSponsor())) {
            mcCouponTxnData.setBankDiscountLimitAmt(mcSubsidyData.getBankDiscountLimitAmt());
            mcCouponTxnData.setMchntDiscountLimitAmt(mcSubsidyData.getMchntDiscountLimitAmt());
        }

        /* 获取交易额度上限  营销活动各维度统计数据获取*/
        returnCode = fetchAllQuotaData(mcCouponTxnData);
        if (CommonConstant.PROCESS_FAILED == returnCode) {
            rglog.info("获取机构<{}>的营销活动<{}>各维度限额和额度失败,本营销活动不予优惠!", globalInstId, mcNo);
            mcCouponTxnData.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
            return;
        }

        /* 判断交易额度上限 */
        returnCode = checkAllQuotaWithMcType(mcCouponTxnData, mcCouponTxnData);
        if (CommonConstant.PROCESS_FAILED == returnCode) {
            rglog.info("机构<{}>的营销活动<{}>判断各维度限额和额度失败,本营销活动不予优惠!", globalInstId, mcNo);
            mcCouponTxnData.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
        }
    }

    /**
     * 卡券类请求报文转换内部对象
     *
     * @param tmCouponInfo    卡券信息表
     * @param mcCouponTxnData (合并)支付使用卡券类交易信息
     * @author Jinan Liu
     * @since 2020/4/17 16:27
     */
    private void convertCouponInfo(TMCouponInfo tmCouponInfo, McCouponTxnData mcCouponTxnData) {

        /* 机构编码 */
        mcCouponTxnData.setInstId(tmCouponInfo.getInstId());
        /* 卡券编号 */
        mcCouponTxnData.setCouponNo(tmCouponInfo.getCouponNo());
        /* 顺序号 */
        mcCouponTxnData.setRuleIndex(tmCouponInfo.getRuleIndex());
        /* 活动门槛 */
        mcCouponTxnData.setCriteria(tmCouponInfo.getCriteria());
        /* 卡券类型 */
        mcCouponTxnData.setCouponType(tmCouponInfo.getCouponType());
        /* 卡券状态 */
        mcCouponTxnData.setCouponStatus(tmCouponInfo.getCouponStatus());
        /* 卡券可抵扣金额 */
        mcCouponTxnData.setCouponAmt(tmCouponInfo.getCouponAmt());
        /* 购买标志 */
        if (!StringUtil.isNullorEmpty(tmCouponInfo.getPurchaseFlag())) {
            mcCouponTxnData.setPurchaseFlag(tmCouponInfo.getPurchaseFlag());
        }
        /* 购买金额 */
        if (!StringUtil.isNullorEmpty(tmCouponInfo.getPurchaseAmt())) {
            mcCouponTxnData.setPurchaseAmt(tmCouponInfo.getPurchaseAmt());
        }
        /* 卡券领取方式 */
        mcCouponTxnData.setClaimType(tmCouponInfo.getClaimType());
        /* 领取人 */
        mcCouponTxnData.setClaimUserId(tmCouponInfo.getClaimUserId());
        /* 领取日期 */
        mcCouponTxnData.setClaimDate(tmCouponInfo.getClaimDate());
        /* 领取时间 */
        mcCouponTxnData.setClaimTime(tmCouponInfo.getClaimTime());
        /* 订单号 */
        if (!StringUtil.isNullorEmpty(tmCouponInfo.getOrderId())) {
            mcCouponTxnData.setPurchaseOrderId(tmCouponInfo.getOrderId());
        }
        /* 核销时间 */
        if (!StringUtil.isNullorEmpty(tmCouponInfo.getRedeemTime())) {
            mcCouponTxnData.setRedeemTime(tmCouponInfo.getRedeemTime());
        }
        /* 卡券有效起始日期 */
        mcCouponTxnData.setAvailStartDate(tmCouponInfo.getCouponStartDate());
        /* 卡券有效结束日期 */
        mcCouponTxnData.setAvailEndDate(tmCouponInfo.getCouponEndDate());
    }

    /**
     * 卡券类请求报文转换内部对象
     *
     * @param tmMcCouponInfo  卡券类营销活动信息表
     * @param mcCouponTxnData (合并)支付使用卡券类交易信息
     * @author Jinan Liu
     * @since 2020/4/18 22:44
     */
    private void convertCouponMcInfo(TMMcCouponInfo tmMcCouponInfo, McCouponTxnData mcCouponTxnData) {

        /* 营销活动编号 */
        mcCouponTxnData.setMcNo(tmMcCouponInfo.getMcNo());
        /* 营销活动名称 */
        mcCouponTxnData.setMcName(tmMcCouponInfo.getMcName());
        /* 营销活动类型 */
        mcCouponTxnData.setMcType(tmMcCouponInfo.getMcType());
        /* 营销活动状态 */
        mcCouponTxnData.setMcStatus(tmMcCouponInfo.getMcStatus());
        /* 活动起始日期 */
        mcCouponTxnData.setMcStartDate(tmMcCouponInfo.getMcStartDate());
        /* 活动截止日期 */
        mcCouponTxnData.setMcEndDate(tmMcCouponInfo.getMcEndDate());
        /* 活动结束日期 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getMcActualEndDate())) {
            mcCouponTxnData.setMcActualEndDate(tmMcCouponInfo.getMcActualEndDate());
        }
        /* 活动时间标志 */
        mcCouponTxnData.setMcTimeFlag(tmMcCouponInfo.getMcTimeFlag());
        /* 出资方 */
        mcCouponTxnData.setSponsor(tmMcCouponInfo.getSponsor());
        /* 参与次数限制 */
        mcCouponTxnData.setRestriction(tmMcCouponInfo.getRestriction());
        /* 客户范围 */
        mcCouponTxnData.setClientRange(tmMcCouponInfo.getClientRange());
        /* 商户范围 */
        mcCouponTxnData.setMerchantRange(tmMcCouponInfo.getMerchantRange());
        /* 新增商户活动标志 */
        mcCouponTxnData.setNewMchntFlag(tmMcCouponInfo.getNewMchntFlag());
        /* 限制金额下限 */
        mcCouponTxnData.setAmtLimitFloor(tmMcCouponInfo.getAmtLimitFloor());
        /* 限制金额上限 */
        mcCouponTxnData.setAmtLimitCelling(tmMcCouponInfo.getAmtLimitCelling());
        /* 预算充值方式 */
        mcCouponTxnData.setBudgetRechargeMethod(tmMcCouponInfo.getBudgetRechargeMethod());
        /* 预算 */
        mcCouponTxnData.setBudget(tmMcCouponInfo.getBudget());
        /* 银行出资预算 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getBankBudget())) {
            mcCouponTxnData.setBankBudget(tmMcCouponInfo.getBankBudget());
        }
        /* 预期参与商户数量 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getExpectMchntQty())) {
            mcCouponTxnData.setExpectMchntQty(tmMcCouponInfo.getExpectMchntQty());
        }
        /* 银行出资比例 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getBankBudgetRatio())) {
            mcCouponTxnData.setBankBudgetRatio(tmMcCouponInfo.getBankBudgetRatio());
        }
        /* 购买标志 */
        mcCouponTxnData.setPurchaseFlag(tmMcCouponInfo.getPurchaseFlag());
        /* 卡券生效时间 */
        mcCouponTxnData.setAvailableDate(tmMcCouponInfo.getAvailableDate());
        /* 卡券有效期标志 */
        mcCouponTxnData.setCouponDateFlag(tmMcCouponInfo.getCouponDateFlag());
        /* 卡券有效起始日期 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getCouponStartDate())) {
            mcCouponTxnData.setCouponStartDate(tmMcCouponInfo.getCouponStartDate());
        }
        /* 卡券有效结束日期 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getCouponStartDate())) {
            mcCouponTxnData.setCouponEndDate(tmMcCouponInfo.getCouponEndDate());
        }
        /* 卡券相对周期 */
        mcCouponTxnData.setCouponPeriod(tmMcCouponInfo.getCouponPeriod());
        /* 卡券库存 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getCouponStartDate())) {
            mcCouponTxnData.setCouponInventory(tmMcCouponInfo.getCouponInventory());
        }
        /* 卡券已领取张数 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getCouponStartDate())) {
            mcCouponTxnData.setCouponClaimed(tmMcCouponInfo.getCouponClaimed());
        }
        /* 卡券未领取张数 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getCouponStartDate())) {
            mcCouponTxnData.setCouponRest(tmMcCouponInfo.getCouponRest());
        }
        /* 卡券已核销张数 */
        if (!StringUtil.isNullorEmpty(tmMcCouponInfo.getCouponStartDate())) {
            mcCouponTxnData.setCouponRedeemed(tmMcCouponInfo.getCouponRedeemed());
        }
        /* 审批状态 */
        mcCouponTxnData.setAuditStatus(tmMcCouponInfo.getAuditStatus());
    }

    /**
     * 接口请求报文和内部对象转换
     *
     * @param comboPaymentRequest (合并)支付接口请求对象
     * @param mcCouponTxnData     (合并)支付使用卡券类交易信息
     * @author Jinan Liu
     * @since 2020/4/17 18:27
     */
    private void convertCouponInfoFromRequest(ComboPaymentRequest comboPaymentRequest, McCouponTxnData mcCouponTxnData) {

        /* 交易日期 */
        mcCouponTxnData.setTransDate(comboPaymentRequest.getHeader().getTransDate());
        /* 交易时间 */
        mcCouponTxnData.setTransTime(comboPaymentRequest.getHeader().getTransTime());
        /* 交易流水号 */
        mcCouponTxnData.setTraceNo(comboPaymentRequest.getHeader().getTraceNo());
        /* 业务产品代码 */
        mcCouponTxnData.setBizProdCode(comboPaymentRequest.getBizProdCode());
        /* 机构编码 */
        mcCouponTxnData.setInstId(comboPaymentRequest.getHeader().getInstId());
        /* 用户编号 */
        mcCouponTxnData.setUserId(comboPaymentRequest.getUserId());
        /* 订单编号 */
        mcCouponTxnData.setOrderId(comboPaymentRequest.getMchntOrderId());
        /* 卡券编号 */
        mcCouponTxnData.setCouponNo(comboPaymentRequest.getCouponInfoList().get(CommonConstant.ZERO).getCouponNo());
    }


    /**
     * 商户手续费减免业务处理分支
     *
     * @param comboPaymentRequest (合并)支付接口请求对象
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/9 13:59
     */
    private int processMchntFeeDiscountProcedure(ComboPaymentRequest comboPaymentRequest) {

        /* 内外报文转换 */
        List<McMchntFeeDiscountTxnData> mchntFeeDiscountTxnDataList = new ArrayList<>();
        comboPaymentRequest.getOrderDetailList().forEach(item -> convertMchntFeeDiscountInfoFromRequest(item, comboPaymentRequest, mchntFeeDiscountTxnDataList));

        /* 判断数据有效性 */
        if (mchntFeeDiscountTxnDataList.isEmpty()) {
            /* 接口里无数据 */
            rglog.info("{}}, TRACE_NO=<{}>", RespCodeEnum.NO_AVAILABLE_DATA_TO_PROCESS_ERROR.getRespDesc(), globalTraceNo);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 逐个商户处理商户手续费优惠类营销活动数据 */
        try {

            /* 计算手续费优惠 */
            for (McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData : mchntFeeDiscountTxnDataList) {

                rglog.info("-----------------------商户<{}> 手续费优惠处理流程开始----------------------------", mcMchntFeeDiscountTxnData.getMchntNo());
                String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();

                calMchntFeeDiscountForSingleMchnt(mcMchntFeeDiscountTxnData);

                BigDecimal zero = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                PaymentOrderDetailBean paymentOrderDetailBean = paymentOrderDetailBeanList.stream().filter(item -> mchntNo.equals(item.getMchntNo())).collect(Collectors.toList()).get(CommonConstant.ZERO);

                if (null == mcMchntFeeDiscountTxnData.getMchntFeeDiscount()) {
                    /* 该子订单未优惠 */
                    paymentOrderDetailBean.setMchntFeeDiscount(zero.toString());
                    paymentOrderDetailBean.setMchntFeeActual(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
                    paymentOrderDetailBean.setMchntFeeDiscountMethod(mcMchntFeeDiscountTxnData.getBudgetRechargeMethod());
                    paymentOrderDetailBean.setMchntFeeReceivable(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
                    paymentOrderDetailBean.setMchntSettleAmt(mcMchntFeeDiscountTxnData.getOrderAmt());

                    continue;
                }

                rglog.info("手续费优惠最终计算结果 MCHNTT_NO<{}>, FEE_DISCOUNT_AMT=<{}>", mcMchntFeeDiscountTxnData.getMchntNo(), mcMchntFeeDiscountTxnData.getMchntFeeDiscount());

                BigDecimal totalSubsidy = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeDiscount()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                //本笔手续费订单金额(接口上送的金额)
                BigDecimal mchntSettleAmt = new BigDecimal(mcMchntFeeDiscountTxnData.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                //本笔手续费优惠订单金额
                BigDecimal mchntFeeDiscountTransAmt = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeDiscountTransAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                /* 判断子订单是否成功优惠 */
                if (CommonConstant.ZERO == zero.compareTo(totalSubsidy) && CommonConstant.ZERO == mchntSettleAmt.compareTo(mchntFeeDiscountTransAmt)) {

                    /* 该子订单未优惠 */
                    paymentOrderDetailBean.setMchntFeeDiscount(zero.toString());
                    paymentOrderDetailBean.setMchntFeeActual(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
                    paymentOrderDetailBean.setMchntFeeDiscountMethod(mcMchntFeeDiscountTxnData.getBudgetRechargeMethod());
                    paymentOrderDetailBean.setMchntFeeReceivable(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
                    paymentOrderDetailBean.setMchntSettleAmt(mcMchntFeeDiscountTxnData.getOrderAmt());

                    rglog.debug("法人机构<{}>的流水号<{}>的商户号<{}>的手续费未享受优惠!", mcMchntFeeDiscountTxnData.getInstId(), mcMchntFeeDiscountTxnData.getTraceNo(), mcMchntFeeDiscountTxnData.getMchntNo());

                } else {

                    /* 子订单有优惠 */
                    paymentOrderDetailBean.setMchntFeeDiscountMcNo(mcMchntFeeDiscountTxnData.getMcNo());
                    paymentOrderDetailBean.setMchntFeeDiscount(totalSubsidy.toString());
                    paymentOrderDetailBean.setMchntFeeActual(mcMchntFeeDiscountTxnData.getMchntFeeActual());
                    paymentOrderDetailBean.setMchntFeeDiscountMethod(mcMchntFeeDiscountTxnData.getBudgetRechargeMethod());
                    paymentOrderDetailBean.setMchntFeeReceivable(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
                    paymentOrderDetailBean.setMchntSettleAmt(mcMchntFeeDiscountTxnData.getOrderAmt());

                    /* 额度更新数据准备,存量商户和新增都需要更新额度 */
                    convertMcLimitDetail(mcMchntFeeDiscountTxnData);

                    //商户号重新赋值，在计算过程中可能变成了上级商户的商户号，登记明细时需要使用自己的商户号
                    mcMchntFeeDiscountTxnData.setMchntNo(mchntNo);
                    /* 订单明细更新数据准备 */
                    convertTxnOrderDetail(mcMchntFeeDiscountTxnData);
                }
            }
        } catch (Exception e) {
            rglog.error("转换营销活动信息异常,异常信息:<{}>", StringUtil.ExceptionToString(e));
            return CommonConstant.PROCESS_FAILED;
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 满减业务处理分支
     *
     * @param comboPaymentRequest (合并)支付接口请求对象
     * @param subsidyAmountList   优惠金额(合并支付使用)
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/9 13:59
     */
    private int processMoneyOffProcedure(ComboPaymentRequest comboPaymentRequest, List<SubsidyAmount> subsidyAmountList) {

        String instId = comboPaymentRequest.getHeader().getInstId();
        String traceNo = comboPaymentRequest.getHeader().getTraceNo();
        String orderId = comboPaymentRequest.getMchntOrderId();

        rglog.info("法人机构号<{}>流水号<{}>订单号<{}>开始处理满减部分业务", instId, traceNo, orderId);

        try {

            /* 内外报文转换 */
            List<McMoneyOffTxnData> mcMoneyOffTxnDataList = new ArrayList<>();
            paymentOrderDetailBeanList.forEach(item -> convertMoneyOffInfoFromRequest(item, comboPaymentRequest, mcMoneyOffTxnDataList));

            /* 判断数据有效性 */
            if (mcMoneyOffTxnDataList.isEmpty()) {
                /* 接口里无数据 */
                rglog.info("<{}>, TRACE_NO=<{}>", RespCodeEnum.NO_AVAILABLE_DATA_TO_PROCESS_ERROR.getRespDesc(), traceNo);
                return CommonConstant.PROCESS_SUCCESS;
            }
            int flag = CommonConstant.FLAG_NOT_SET;
            /* 按商户处理减免类营销活动数据处理,计算减免类优惠 */
            for (McMoneyOffTxnData mcMoneyOffTxnData : mcMoneyOffTxnDataList) {
                rglog.info("###############################开始处理商户<{}>的减免类营销活动数据#############################", mcMoneyOffTxnData.getMchntNo());

                if (null != paymentOrderMoneyOffInfoBeanList && !paymentOrderMoneyOffInfoBeanList.isEmpty()) {
                    if (flag == CommonConstant.FLAG_NOT_SET) {
                        /* 获取商户基本信息,每个商户订单单独处理 */
                        TBMchntBaseInfo tbMchntBaseInfo = tbMchntBaseInfoList.stream().filter(object -> object.getMchntNo().equals(mcMoneyOffTxnData.getMchntNo())).collect(Collectors.toList()).get(CommonConstant.ZERO);
                        /* 使用商户基本信息获取指定商户的营销活动商户列表*/
                        List<TMMcMchntInfo> tmMcMchntInfoList = matchMcMchntInfoByUsingMchntInfoAndMcNo(tbMchntBaseInfo, paymentOrderMoneyOffInfoBeanList.get(0).getMcNo());
                        if (null != tmMcMchntInfoList && !tmMcMchntInfoList.isEmpty()) {
                            /* 若营销活动商户列表中存在数据,则每个列表中的对象都单独计算,取额度限制比较前优惠力度最高的营销活动进行优惠 */
                            int returnCode = checkMoneyOffMcPrerequisiteInfo(mcMoneyOffTxnData, tmMcMchntInfoList);
                            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                                /* 计算失败,当前商户无优惠 */
                                rglog.info("商户<{}>无进行中的减免类活动或计算优惠信息失败! RETURN_CODE=<{}>", mcMoneyOffTxnData.getMchntNo(), returnCode);
                            } else {
                                flag = CommonConstant.FLAG_SET;
                            }
                        } else {
                            if (StringUtil.isNullorEmpty(tbMchntBaseInfo.getMchntArea())) {
                                rglog.info("使用商户号MCHNT_NO=<{}>未找到对应匹配的营销活动信息! INST_ID=<{}>", mcMoneyOffTxnData.getMchntNo(), instId);
                            } else {
                                rglog.info("使用商户号MCHNT_NO=<{}>和商圈编号MCHNT_AREA=<{}>均未找到对应匹配的营销活动信息! INST_ID=<{}>", mcMoneyOffTxnData.getMchntNo(), tbMchntBaseInfo.getMchntArea(), instId);
                            }
                        }
                    }
                } else {
                    //计算单个商户的减免类优惠情况
                    calMoneyOffDiscountForSingleMchnt(mcMoneyOffTxnData);
                }
                rglog.debug("TOTAL_SUBSIDY=<{}>", mcMoneyOffTxnData.getTotalSubsidy());

                String mchntNo = mcMoneyOffTxnData.getMchntNo();
                BigDecimal totalSubsidy = new BigDecimal(mcMoneyOffTxnData.getTotalSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal zero = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                PaymentOrderDetailBean paymentOrderDetailBean = paymentOrderDetailBeanList.stream().filter(item -> mchntNo.equals(item.getMchntNo())).collect(Collectors.toList()).get(CommonConstant.ZERO);
                SubsidyAmount subsidyAmount = subsidyAmountList.stream().filter(item -> mchntNo.equals(item.getMchntNo())).collect(Collectors.toList()).get(CommonConstant.ZERO);

                BigDecimal orderAmt = new BigDecimal(paymentOrderDetailBean.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal txnAmt = orderAmt.subtract(totalSubsidy).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                /* 判断子订单是否成功优惠 */
                if (CommonConstant.ZERO == zero.compareTo(totalSubsidy)) {

                    /* 该子订单未优惠 */
                    paymentOrderDetailBean.setMoneyOffTxnAmt(txnAmt.toString());
                    paymentOrderDetailBean.setMoneyOffSubsidyTotal(CommonConstant.ZERO_AMOUNT);
                    paymentOrderDetailBean.setMoneyOffSubsidyBank(CommonConstant.ZERO_AMOUNT);
                    paymentOrderDetailBean.setMoneyOffSubsidyMchnt(CommonConstant.ZERO_AMOUNT);
                } else {

                    /* 子订单有优惠 */
                    paymentOrderDetailBean.setMoneyOffMcNo(mcMoneyOffTxnData.getMcNo());
                    paymentOrderDetailBean.setMoneyOffTxnAmt(txnAmt.toString());
                    paymentOrderDetailBean.setMoneyOffSubsidyTotal(mcMoneyOffTxnData.getTotalSubsidy());
                    paymentOrderDetailBean.setMoneyOffSubsidyBank(mcMoneyOffTxnData.getBankSubsidy());
                    paymentOrderDetailBean.setMoneyOffSubsidyMchnt(mcMoneyOffTxnData.getMchntSubsidy());
                    paymentOrderDetailBean.setMoneyOffSettlementMethod(mcMoneyOffTxnData.getBudgetRechargeMethod());

                    BigDecimal bankSubsidy = new BigDecimal(mcMoneyOffTxnData.getBankSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    BigDecimal mchntSubsidy = new BigDecimal(mcMoneyOffTxnData.getMchntSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    subsidyAmount.setTotalSubsidy(totalSubsidy);
                    subsidyAmount.setBankSubsidy(bankSubsidy);
                    subsidyAmount.setMchntSubsidy(mchntSubsidy);

                    /* 额度更新数据准备 */
                    convertMcLimitDetail(mcMoneyOffTxnData);

                    /* 订单明细更新数据准备 */
                    convertTxnOrderDetail(mcMoneyOffTxnData);
                }
            }

        } catch (Exception e) {
            rglog.error("处理商户减免类营销活动数据异常,异常信息:<{}>", StringUtil.ExceptionToString(e));

            /* 接口对象列表、订单明细和对客类减免统计表数据重置 */
            for (PaymentOrderDetailBean paymentOrderDetailBean : paymentOrderDetailBeanList) {
                /* 重置子订单接口对象数据 */
                paymentOrderDetailBean.setMoneyOffMcNo("");
                paymentOrderDetailBean.setMoneyOffTxnAmt(paymentOrderDetailBean.getOrderAmt());
                paymentOrderDetailBean.setMoneyOffSubsidyTotal(CommonConstant.ZERO_AMOUNT);
                paymentOrderDetailBean.setMoneyOffSubsidyBank(CommonConstant.ZERO_AMOUNT);
                paymentOrderDetailBean.setMoneyOffSubsidyMchnt(CommonConstant.ZERO_AMOUNT);
                paymentOrderDetailBean.setMoneyOffSettlementMethod("");
            }

            /* 接口对象列表、订单明细和对客类减免统计表数据重置 */
            for (SubsidyAmount subsidyAmount : subsidyAmountList) {
                subsidyAmount.setTotalSubsidy(BigDecimal.ZERO);
                subsidyAmount.setBankSubsidy(BigDecimal.ZERO);
                subsidyAmount.setMchntSubsidy(BigDecimal.ZERO);
            }

            /* 订单明细数据重置 */
            tmTxnOrderDetList.removeIf(tmTxnOrderDet -> tmTxnOrderDet.getMcNo().startsWith("MC0"));

            /* 对客户营销活动单日统计表数据重置 */
            tmStat2CDayList.removeIf(tmStat2CDay -> tmStat2CDay.getMcNo().startsWith("MC0"));

            /* 对客户营销活动商户单日统计表数据重置 */
            tmStat2CMchntDayList.removeIf(tmStat2CMchntDay -> tmStat2CMchntDay.getMcNo().startsWith("MC0"));

            return CommonConstant.PROCESS_FAILED;
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 计算单个商户的减免类优惠情况
     *
     * @param mcMoneyOffTxnData (合并)支付使用减免类交易信息
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/13 16:11
     */
    private void calMoneyOffDiscountForSingleMchnt(McMoneyOffTxnData mcMoneyOffTxnData) throws Exception {

        String instId = mcMoneyOffTxnData.getInstId();
        String mchntNo = mcMoneyOffTxnData.getMchntNo();

        /* 获取商户基本信息,每个商户订单单独处理 */
        TBMchntBaseInfo tbMchntBaseInfo = tbMchntBaseInfoList.stream().filter(object -> object.getMchntNo().equals(mchntNo)).collect(Collectors.toList()).get(CommonConstant.ZERO);

        /* 使用商户基本信息获取指定商户的营销活动商户列表*/
        List<TMMcMchntInfo> tmMcMchntInfoList = matchMcMchntInfoByUsingMchntInfo(tbMchntBaseInfo);
        if (null == tmMcMchntInfoList || tmMcMchntInfoList.isEmpty()) {
            if (StringUtil.isNullorEmpty(tbMchntBaseInfo.getMchntArea())) {
                rglog.info("使用商户号MCHNT_NO=<{}>未找到对应匹配的营销活动信息! INST_ID=<{}>", mchntNo, instId);
            } else {
                rglog.info("使用商户号MCHNT_NO=<{}>和商圈编号MCHNT_AREA=<{}>均未找到对应匹配的营销活动信息! INST_ID=<{}>", mchntNo, tbMchntBaseInfo.getMchntArea(), instId);
            }
            return;
        }

        /* 若营销活动商户列表中存在数据,则每个列表中的对象都单独计算,取额度限制比较前优惠力度最高的营销活动进行优惠 */
        int returnCode = checkMoneyOffMcPrerequisiteInfo(mcMoneyOffTxnData, tmMcMchntInfoList);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            /* 计算失败,当前商户无优惠 */
            rglog.info("商户<{}>无进行中的减免类活动或计算优惠信息失败! RETURN_CODE=<{}>", mchntNo, returnCode);
        }
    }

    /**
     * 计算单个商户的商户手续费优惠类优惠情况
     *
     * @param mcMchntFeeDiscountTxnData (合并)支付使用商户手续费优惠类营销活动交易信息
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 10:16
     */
    private void calMchntFeeDiscountForSingleMchnt(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {

        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();

        /* 获取商户基本信息,每个商户订单单独处理 */
        TBMchntBaseInfo tbMchntBaseInfo = tbMchntBaseInfoList.stream().filter(object -> object.getMchntNo().equals(mchntNo)).collect(Collectors.toList()).get(CommonConstant.ZERO);

        /* 若商户列表中存在数据,则每个列表中的对象都单独计算,取额度限制比较前优惠力度最高的营销活动进行优惠 */
        int returnCode = checkMchntFeeDiscountMcPrerequisiteInfo(mcMchntFeeDiscountTxnData, tbMchntBaseInfo);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            /* 计算失败,当前商户无优惠 */
            rglog.info("商户<{}>无进行中的商户手续费优惠类活动或计算优惠信息失败! RETURN_CODE=<{}>", mchntNo, returnCode);
            mcMchntFeeDiscountTxnData.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT);
            mcMchntFeeDiscountTxnData.setMchntFeeActual(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
        }
    }

    /**
     * 将接口订单明细转换为内部实体类
     *
     * @param paymentOrderDetailBean 订单明细
     * @param comboPaymentRequest    (合并)支付接口请求对象
     * @param mcMchntOrderDataList   营销活动商户订单明细实体类
     * @author Jinan Liu
     * @since 2020/4/18 11:09
     */
    private void convertMcMchntOrderInfoFromRequest(PaymentOrderDetailBean paymentOrderDetailBean, ComboPaymentRequest comboPaymentRequest, List<McMchntOrderData> mcMchntOrderDataList) {

        McMchntOrderData mcMchntOrderData = new McMchntOrderData();

        /* 交易日期 */
        mcMchntOrderData.setTransDate(comboPaymentRequest.getHeader().getTransDate());
        /* 交易时间 */
        mcMchntOrderData.setTransTime(comboPaymentRequest.getHeader().getTransTime());
        /* 交易流水号 */
        mcMchntOrderData.setTraceNo(comboPaymentRequest.getHeader().getTraceNo());
        /* 业务产品代码 */
        mcMchntOrderData.setBizProdCode(comboPaymentRequest.getBizProdCode());
        /* 机构编码 */
        mcMchntOrderData.setInstId(comboPaymentRequest.getHeader().getInstId());
        /* 商户编号 */
        mcMchntOrderData.setMchntNo(paymentOrderDetailBean.getMchntNo());
        /* 订单金额 */
        mcMchntOrderData.setOrderAmt(paymentOrderDetailBean.getOrderAmt());
        /* 订单金额 */
        mcMchntOrderData.setOrderAmtNum(new BigDecimal(paymentOrderDetailBean.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP));
        /* 用户编号 */
        mcMchntOrderData.setUserId(comboPaymentRequest.getUserId());
        /* 订单编号 */
        mcMchntOrderData.setOrderId(comboPaymentRequest.getMchntOrderId());

        mcMchntOrderDataList.add(mcMchntOrderData);
    }

    /**
     * 减免类请求报文转换内部对象
     *
     * @param paymentOrderDetailBean 订单明细
     * @param comboPaymentRequest    (合并)支付接口请求对象
     * @param mcMoneyOffTxnDataList  (合并)支付使用减免类交易信息
     * @author Jinan Liu
     * @since 2020/4/14 09:52
     */
    private void convertMoneyOffInfoFromRequest(PaymentOrderDetailBean paymentOrderDetailBean, ComboPaymentRequest comboPaymentRequest, List<McMoneyOffTxnData> mcMoneyOffTxnDataList) {

        McMoneyOffTxnData mcMoneyOffTxnData = new McMoneyOffTxnData();

        /* 交易日期 */
        mcMoneyOffTxnData.setTransDate(comboPaymentRequest.getHeader().getTransDate());
        /* 交易时间 */
        mcMoneyOffTxnData.setTransTime(comboPaymentRequest.getHeader().getTransTime());
        /* 交易流水号 */
        mcMoneyOffTxnData.setTraceNo(comboPaymentRequest.getHeader().getTraceNo());
        /* 业务产品代码 */
        mcMoneyOffTxnData.setBizProdCode(comboPaymentRequest.getBizProdCode());
        /* 机构编码 */
        mcMoneyOffTxnData.setInstId(comboPaymentRequest.getHeader().getInstId());
        /* 商户编号 */
        mcMoneyOffTxnData.setMchntNo(paymentOrderDetailBean.getMchntNo());

        if (mcCouponTxnData != null) {
            if (paymentOrderDetailBean.getMchntNo().equals(mcCouponTxnData.getMchntNo())) {
                /* 已经核销卡券的子订单,用来计算的订单金额=订单金额-卡券面额 */
                BigDecimal orderAmt = new BigDecimal(paymentOrderDetailBean.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal couponAmt = new BigDecimal(mcCouponTxnData.getCouponAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal newOrderAmt = orderAmt.subtract(couponAmt).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                mcMoneyOffTxnData.setOrderAmt(newOrderAmt.toString());
            } else {
                /* 订单金额 */
                mcMoneyOffTxnData.setOrderAmt(paymentOrderDetailBean.getOrderAmt());
            }
        } else {
            /* 订单金额 */
            mcMoneyOffTxnData.setOrderAmt(paymentOrderDetailBean.getOrderAmt());
        }

        /* 用户编号 */
        mcMoneyOffTxnData.setUserId(comboPaymentRequest.getUserId());
        /* 订单编号 */
        mcMoneyOffTxnData.setOrderId(comboPaymentRequest.getMchntOrderId());

        /* 总优惠金额 */
        mcMoneyOffTxnData.setTotalSubsidy(CommonConstant.ZERO_AMOUNT);
        /* 银行优惠金额 */
        mcMoneyOffTxnData.setBankSubsidy(CommonConstant.ZERO_AMOUNT);
        /* 商户优惠金额 */
        mcMoneyOffTxnData.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);

        mcMoneyOffTxnDataList.add(mcMoneyOffTxnData);
    }

    /**
     * 手续费优惠类请求报文转换内部对象
     *
     * @param paymentOrderDetailBean      订单明细
     * @param comboPaymentRequest         (合并)支付接口请求对象
     * @param mchntFeeDiscountTxnDataList (合并)支付使用商户手续费优惠类营销活动交易信息
     * @author Jinan Liu
     * @since 2020/4/20 10:06
     */
    private void convertMchntFeeDiscountInfoFromRequest(PaymentOrderDetailBean paymentOrderDetailBean, ComboPaymentRequest comboPaymentRequest, List<McMchntFeeDiscountTxnData> mchntFeeDiscountTxnDataList) {

        McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData = new McMchntFeeDiscountTxnData();

        /* 交易日期 */
        mcMchntFeeDiscountTxnData.setTransDate(comboPaymentRequest.getHeader().getTransDate());
        /* 交易时间 */
        mcMchntFeeDiscountTxnData.setTransTime(comboPaymentRequest.getHeader().getTransTime());
        /* 交易流水号 */
        mcMchntFeeDiscountTxnData.setTraceNo(comboPaymentRequest.getHeader().getTraceNo());
        /* 业务产品代码 */
        mcMchntFeeDiscountTxnData.setBizProdCode(comboPaymentRequest.getBizProdCode());
        /* 机构编码 */
        mcMchntFeeDiscountTxnData.setInstId(comboPaymentRequest.getHeader().getInstId());
        /* 商户编号 */
        mcMchntFeeDiscountTxnData.setMchntNo(paymentOrderDetailBean.getMchntNo());
        /* 订单金额(使用接口中的商户清算金额作为计算商户手续费优惠的订单金额) */
        mcMchntFeeDiscountTxnData.setOrderAmt(paymentOrderDetailBean.getMchntSettleAmt());
        /* 手续费收取方式 */
        mcMchntFeeDiscountTxnData.setFeeInputMode(paymentOrderDetailBean.getFeeInputMode());
        /* 费率类型 */
        mcMchntFeeDiscountTxnData.setFeeType(paymentOrderDetailBean.getFeeType());
        /* 业务产品代码 */
        mcMchntFeeDiscountTxnData.setCalMchntFeeBizProdCode(paymentOrderDetailBean.getBizProdCode());
        /* 商户应收手续费金额 */
        mcMchntFeeDiscountTxnData.setMchntFeeReceivable(paymentOrderDetailBean.getMchntFeeReceivable());
        /* 商户应收手续费费率 */
        mcMchntFeeDiscountTxnData.setMchntFeeReceivableRate(paymentOrderDetailBean.getMchntFeeReceivableRate());
        /* 用户编号 */
        mcMchntFeeDiscountTxnData.setUserId(comboPaymentRequest.getUserId());
        /* 订单编号 */
        mcMchntFeeDiscountTxnData.setOrderId(comboPaymentRequest.getMchntOrderId());
        /*商户优惠交易金额  初始值为上送的商户清算金额*/
        mcMchntFeeDiscountTxnData.setMchntFeeDiscountTransAmt(paymentOrderDetailBean.getMchntSettleAmt());

        mchntFeeDiscountTxnDataList.add(mcMchntFeeDiscountTxnData);
    }

    /**
     * 使用商户号和商户所在商圈编号匹配营销活动商户信息表中数据
     *
     * @param mchntBaseInfo 商户基本信息表T_B_MCHNT_BASE_INFO
     * @return java.util.List<cc.rengu.igas.momp.common.entity.TMMcMchntInfo> 营销活动商户信息表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/13 15:10
     */
    private List<TMMcMchntInfo> matchMcMchntInfoByUsingMchntInfo(TBMchntBaseInfo mchntBaseInfo) throws Exception {

        McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
        return mcMchntInfoMapper.matchMoMcInfoByMchntNoAndMchntArea(mchntBaseInfo);
    }

    /**
     * `检查减免类营销活动优惠条件
     *
     * @param mcMoneyOffTxnData (合并)支付使用减免类交易信息
     * @param tmMcMchntInfoList 营销活动商户信息表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/14 09:25
     */
    private int checkMoneyOffMcPrerequisiteInfo(McMoneyOffTxnData mcMoneyOffTxnData, List<TMMcMchntInfo> tmMcMchntInfoList) throws Exception {

        int retCode;
        String instId = mcMoneyOffTxnData.getInstId();
        String mchntNo = mcMoneyOffTxnData.getMchntNo();

        /* 取营销活动基本信息的列表 */
        List<TMMcMoneyOffInfo> tmMcMoneyOffInfoList = new ArrayList<>();
        tmMcMchntInfoList.forEach(item -> getMoneyOffMcInfo(item, tmMcMoneyOffInfoList));
        if (tmMcMoneyOffInfoList.isEmpty()) {
            rglog.info("未获取到营销活动信息!");
            return CommonConstant.PROCESS_FAILED;
        }
        rglog.info("机构<{}> 商户<{}> 共查询到<{}>个符合条件的减免类营销活动信息!继续后续流程!", instId, mchntNo, tmMcMoneyOffInfoList.size());

        List<MoneyOffAmountData> moneyOffAmountDataList = new ArrayList<>();

        /* 逐个营销活动进行处理 */
        for (TMMcMoneyOffInfo tmMcMoneyOffInfo : tmMcMoneyOffInfoList) {
            rglog.info("-------------------------------------------商户<{}> 减免类营销活动<{}> 开始处理流程----------------------------", mchntNo, tmMcMoneyOffInfo.getMcNo());
            /* 单个营销活动处理失败不做进一步处理,流程继续 */
            String mcNo = tmMcMoneyOffInfo.getMcNo();
            String mcType = tmMcMoneyOffInfo.getMcType();

            /* 检查营销活动状态 */
            retCode = checkMcStatus(tmMcMoneyOffInfo);
            if (CommonConstant.PROCESS_SUCCESS != retCode) {
                rglog.error("机构<{}>的减免类营销活动<{}>信息校验失败!该营销活动不可参与营销! RETURN_CODE=<{}>", instId, mcNo, retCode);
                continue;
            }
            rglog.info("机构<{}>的减免类营销活动<{}>营销活动状态和运行时间信息校验成功!继续校验后续信息! RETURN_CODE=<{}>", instId, mcNo, retCode);

            /* 判断是否支持支付产品-无需记录对应的时间规则 */
            retCode = checkMompProductSupportInfo(instId, mcNo, mcMoneyOffTxnData.getBizProdCode());
            if (CommonConstant.PROCESS_SUCCESS != retCode) {
                rglog.error("机构<{}>的营销活动<{}>不支持营销产品<{}>", instId, mcNo, mcMoneyOffTxnData.getBizProdCode());
                continue;
            }
            rglog.info("机构<{}>的营销活动<{}>支持营销产品<{}>,继续校验后续信息!", instId, mcNo, mcMoneyOffTxnData.getBizProdCode());

            /* 判断是否在营销活动允许的时间范围内-无需记录对应的时间规则 */
            if (CommonConstant.ALL_TIME_SUPPORT.equals(tmMcMoneyOffInfo.getMcTimeFlag())) {
                rglog.info("机构<{}>的营销活动<{}>在任意时间段内可用!继续校验后续信息!", instId, mcNo);
            } else if (CommonConstant.SPECIFIC_TIME_SUPPORT.equals(tmMcMoneyOffInfo.getMcTimeFlag())) {
                rglog.info("机构<{}>的营销活动<{}>在指定时间段内可用,需要进一步判断当前时间!", instId, mcNo);
                List<TMMcTimeInfo> tmMcTimeInfoList = getAllMcTimeListInfo(instId, mcNo);
                if (null == tmMcTimeInfoList || tmMcTimeInfoList.isEmpty()) {
                    rglog.info("获取机构<{}>的营销活动<{}>时间规则信息失败,本营销活动不予优惠!", instId, mcNo);
                    continue;
                } else {
                    retCode = checkMcTimeInfo(mcMoneyOffTxnData.getTransDate(), mcMoneyOffTxnData.getTransTime(), tmMcTimeInfoList);
                    if (CommonConstant.PROCESS_SUCCESS != retCode) {
                        rglog.info("获取机构<{}>的营销活动<{}>时间规则信息匹配失败,本营销活动不予优惠!", instId, mcNo);
                        continue;
                    } else {
                        rglog.info("获取机构<{}>的营销活动<{}>时间规则信息匹配成功,继续校验后续信息!", instId, mcNo);
                    }
                }
            } else {
                rglog.error("机构<{}>的营销活动<{}>活动时间标志<{}>异常,本营销活动不予优惠!", instId, mcNo, tmMcMoneyOffInfo.getMcTimeFlag());
                continue;
            }

            //客户范围 0:所有人 1：指定用户
            String clientRange = tmMcMoneyOffInfo.getClientRange();
            //查询该活动下所有营销用户消息
            List<TMMcUserInfo> allUserInfoList = selectMcUserList(globalInstId, mcNo);
            //指定用户
            if (clientRange.equals(CommonConstant.SPECIFIC_CLIENT_SUPPORT)) {
                rglog.info("活动<{}>客户范围为指定用户", mcNo);
                if (allUserInfoList == null || allUserInfoList.size() == 0) {
                    rglog.info("获取机构<{}>的营销活动<{}>用户信息匹配失败,本营销活动不予优惠!", globalInstId, mcNo);
                    throw new BizException(RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespCode(), RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespDesc());
                }
                acctType = allUserInfoList.get(CommonConstant.ZERO).getAcctType();
                //上送userId为json字符串
                if (userIdFlag.equals(CommonConstant.THREE_COMMON_CONSTANT)) {
                    rglog.info("上送userId<{}>为Json字符串", globalUserId);
                    if (acctType.equals(CommonConstant.ZERO_COMMON_CONSTANT)) {
                        if (StringUtil.isNullorEmpty(phoneNo)) {
                            rglog.error("营销活动编号 MC_NO=<{}> 为指定手机号领取，但未上送手机号", mcNo);
                            continue;
                        }
                        rglog.info("活动<{}>指定用户类型为手机号<{}>", mcNo, phoneNo);
                        discountId = phoneNo;
                    } else if (acctType.equals(CommonConstant.ONE_COMMON_CONSTANT) || acctType.equals(CommonConstant.TWO_COMMON_CONSTANT) || acctType.equals(CommonConstant.THREE_COMMON_CONSTANT)) {
                        if (StringUtil.isNullorEmpty(cardNo)) {
                            rglog.error("营销活动编号 MC_NO=<{}> 为指定银行卡号或卡bin或卡产品领取，但未上送银行卡号", mcNo);
                            continue;
                        }
                        rglog.info("活动<{}>指定用户类型为指定银行卡号或卡bin或卡产品领取", mcNo, cardNo);
                        discountId = cardNo;
                    } else {
                        rglog.info("机构号<{}>营销活动<{}>营销用户账户类型错误!", globalInstId, mcNo);
                        throw new BizException(RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespCode(), RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespDesc());
                    }
                } else if (userIdFlag.equals(CommonConstant.TWO_COMMON_CONSTANT)) {
                    rglog.info("上送userId<{}>不是Json字符串", globalUserId);
                    discountId = globalUserId;
                } else {

                }
            } else {
                rglog.info("活动<{}>客户范围为所有人", mcNo);
                if (null == mcCouponTxnData) {
                    rglog.info("未上送卡券信息，如上送卡券信息，减免类活动优惠优先使用卡券核销时所用userId");
                    if (userIdFlag.equals(CommonConstant.THREE_COMMON_CONSTANT)) {
                        if (!StringUtil.isNullorEmpty(cardNo)) {
                            rglog.info("上送Json字符串有卡号<{}>,优先领取人为卡号", cardNo);
                            discountId = cardNo;
                        } else if (StringUtil.isNullorEmpty(cardNo) && !StringUtil.isNullorEmpty(phoneNo)) {
                            rglog.info("上送Json字符串无卡号且上送了手机号<{}>,优先领取人为手机号", phoneNo);
                            discountId = phoneNo;
                        } else if (StringUtil.isNullorEmpty(cardNo) && StringUtil.isNullorEmpty(phoneNo) && !StringUtil.isNullorEmpty(wechatId)) {
                            rglog.info("上送Json字符串无卡号无手机号，上送了wechatId<{}>,优先领取人为wechatId", wechatId);
                            discountId = wechatId;
                        } else if (StringUtil.isNullorEmpty(cardNo) && StringUtil.isNullorEmpty(phoneNo) && !StringUtil.isNullorEmpty(alipayId)) {
                            rglog.info("上送Json字符串无卡号无手机号，上送了alipayId<{}>,优先领取人为alipayId", alipayId);
                            discountId = alipayId;
                        } else if (StringUtil.isNullorEmpty(cardNo) && StringUtil.isNullorEmpty(phoneNo) && StringUtil.isNullorEmpty(alipayId)
                                && StringUtil.isNullorEmpty(wechatId) && !StringUtil.isNullorEmpty(coreComId)) {
                            rglog.info("上送Json字符串无卡号无手机号无支付宝id无微信id，上送了核心客户号<{}>,优先领取人为核心客户号", coreComId);
                            discountId = coreComId;
                        } else {
                            rglog.info("上送userId不符合");
                            continue;
                        }
                    } else if (userIdFlag.equals(CommonConstant.TWO_COMMON_CONSTANT)) {
                        rglog.info("上送userId<{}>不是Json字符串", globalUserId);
                        discountId = globalUserId;
                    } else {

                    }
                } else {
                    rglog.info("已上送卡券信息，减免类活动优惠优先使用卡券核销时所用userId");
                    discountId = mcCouponTxnData.getUserId();
                }
            }
            mcMoneyOffTxnData.setUserId(discountId);
            //查询该用户，活动下的营销用户信息表信息 目前只支持减免类活动卡bin 卡产品
            List<TMMcUserInfo> userInfoList = checkUserInfo(instId, mcNo, discountId);
            //没有配置手机号 银行卡号 卡bin，查询有没有配置卡产品
            if (null == userInfoList || userInfoList.size() == 0) {
                if (discountId.length() >= 10) {
                    McUserInfoMapper mcUserInfoMapper = new McUserInfoMapperImpl();
                    userInfoList = mcUserInfoMapper.selectMcUserInfoListByInstIdMcNoAcctNo(globalInstId, mcNo, discountId.substring(0, 10));
                }
            }
            if (!StringUtil.isNullorEmpty(tmMcMoneyOffInfo.getRemark1()) && "802".equals(tmMcMoneyOffInfo.getInstId()) && "802SJQY".equals(tmMcMoneyOffInfo.getRemark1())) {
                rglog.info("该活动是老平台潍坊行活动<{}>，走老平台营销规则", mcNo);
                boolean checkWeiFangOldRule = checkWeiFangOldRule(tmMcMoneyOffInfo);
                if (!checkWeiFangOldRule) {
                    rglog.info("获取机构<{}>的营销活动<{}>优惠次数校验失败,本营销活动不予优惠!", instId, mcNo);
                    continue;
                }
            } else if (CommonConstant.PRK_BUSN_FLG_YES.equals(tmMcMoneyOffInfo.getPrkBusnFlg()) && "802".equals(tmMcMoneyOffInfo.getInstId())) {
                rglog.info("该活动是新平台潍坊行停车场活动<{}>，走单独营销规则", mcNo);
                boolean checkPrkAvyRule = checkPrkAvyRule(tmMcMoneyOffInfo);
                if (!checkPrkAvyRule) {
                    rglog.info("获取机构<{}>的营销活动<{}>优惠次数校验失败,本营销活动不予优惠!", instId, mcNo);
                    continue;
                }
            } else {
                //测试账户
                List<TMMcUserInfo> testUserInfoList = new ArrayList<>();
                //正式账户
                List<TMMcUserInfo> formalUserInfoList = new ArrayList<>();
                if (null != userInfoList && userInfoList.size() > 0) {
                    testUserInfoList = userInfoList.stream().filter(item -> item.getAcctFlag().equals(CommonConstant.ACCT_FLAG_TESTING)).collect(Collectors.toList());
                    formalUserInfoList = userInfoList.stream().filter(item -> item.getAcctFlag().equals(CommonConstant.ACCT_FLAG_NORMAL)).collect(Collectors.toList());
                }
                /* 判断用户是否在营销活动允许的用户范围内-无需记录对应的用户规则 */
                if (CommonConstant.ALL_CLIENT_SUPPORT.equals(tmMcMoneyOffInfo.getClientRange())) {
                    rglog.info("机构<{}>的营销活动<{}>支持对所有用户减免,继续校验后续信息!", instId, mcNo);
                    if (tmMcMoneyOffInfo.getMcStatus().equals(McStatusEnum.TESTING.getMcStatusCode()) && testUserInfoList.size() == 0) {
                        rglog.info("获取机构<{}>的营销活动<{}>用户信息匹配失败,本营销活动不予优惠!", instId, mcNo);
                        continue;
                    }
                    //判断用户参与活动次数是否超过活动配置的限制次数——不限定用户
                    Boolean userAttendIsReachLimit = checkIsUserReachLimit(tmMcMoneyOffInfo, null);
                    if (!userAttendIsReachLimit) {
                        rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数大于等于最大限制，不可再参与本活动！", mcMoneyOffTxnData.getUserId(), mcNo);
                        continue;
                    }
                } else if (CommonConstant.SPECIFIC_CLIENT_SUPPORT.equals(tmMcMoneyOffInfo.getClientRange())) {
                    rglog.info("机构<{}>的营销活动<{}>支持对部分用户减免,需要进一步判断当前用户!", instId, mcNo);

                    if (formalUserInfoList.size() > 0 && tmMcMoneyOffInfo.getMcStatus().equals(McStatusEnum.PROGRESSING.getMcStatusCode())) {
                        rglog.info("获取机构<{}>的营销活动<{}>用户信息匹配成功,继续校验后续信息!", instId, mcNo);
                        //判断用户参与活动次数是否超过活动配置的限制次数——正式用户
                        Boolean userAttendIsReachLimit = checkIsUserReachLimit(tmMcMoneyOffInfo, formalUserInfoList);
                        if (!userAttendIsReachLimit) {
                            rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数大于等于最大限制，不可再参与本活动！", mcMoneyOffTxnData.getUserId(), mcNo);
                            continue;
                        }
                    } else if (testUserInfoList.size() > 0 && tmMcMoneyOffInfo.getMcStatus().equals(McStatusEnum.TESTING.getMcStatusCode())) {
                        rglog.info("获取机构<{}>的营销活动<{}>用户信息匹配成功,继续校验后续信息!", instId, mcNo);
                        //判断用户参与活动次数是否超过活动配置的限制次数——测试用户
                        Boolean userAttendIsReachLimit = checkIsUserReachLimit(tmMcMoneyOffInfo, testUserInfoList);
                        if (!userAttendIsReachLimit) {
                            rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数大于等于最大限制，不可再参与本活动！", mcMoneyOffTxnData.getUserId(), mcNo);
                            continue;
                        }
                    } else {
                        rglog.info("获取机构<{}>的营销活动<{}>用户信息匹配失败,本营销活动不予优惠!", instId, mcNo);
                        continue;
                    }
                } else {
                    rglog.error("机构<{}>的营销活动<{}>客户范围<{}>异常,本营销活动不予优惠!", instId, mcNo, tmMcMoneyOffInfo.getClientRange());
                    continue;
                }
            }

            /* 取营销活动规则 */
            List<TMMcMoneyOffRuleInfo> tmMcMoneyOffRuleInfoList = selectMoneyOffRuleInfoList(instId, mcNo);
            if (null == tmMcMoneyOffRuleInfoList) {
                /* 未取到营销活动规则信息,本营销活动不可以优惠! */
                rglog.info("获取机构<{}>的营销活动<{}>减免规则信息匹配失败,本营销活动不予优惠!", instId, mcNo);
                continue;
            }

            /* 取符合条件的优惠最高的档次判断是否可以优惠 */
            //TMMcMoneyOffRuleInfo tmMcMoneyOffRuleInfo;
            BigDecimal orderAmt = new BigDecimal(mcMoneyOffTxnData.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.debug("ORDER_AMT=<{}>", orderAmt.toString());

            List<TMMcMoneyOffRuleInfo> tmMcMoneyOffRuleInfoList1 = new ArrayList<>();
            for (TMMcMoneyOffRuleInfo tmMcMoneyOffRuleInfo1 : tmMcMoneyOffRuleInfoList) {
                BigDecimal criteriaAmt = new BigDecimal(tmMcMoneyOffRuleInfo1.getCriteria()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                if (CommonConstant.ZERO >= criteriaAmt.compareTo(orderAmt)) {
                    tmMcMoneyOffRuleInfoList1.add(tmMcMoneyOffRuleInfo1);
                }
            }
            if (tmMcMoneyOffRuleInfoList1.isEmpty()) {
                rglog.info("订单金额<{}>不满足法人机构<{}>的减免类营销活动<{}>的任意一档规则,本营销活动不予优惠!", mcMoneyOffTxnData.getOrderAmt(), globalInstId, mcNo);
                continue;
            } else {
                //根据规则顺序号由大到小排序
                Comparator<TMMcMoneyOffRuleInfo> ruleIndex = Comparator.comparingDouble((TMMcMoneyOffRuleInfo tmMcMoneyOffRuleInfo1) -> Double.parseDouble(tmMcMoneyOffRuleInfo1.getRuleIndex())).reversed();
                tmMcMoneyOffRuleInfoList1.sort(ruleIndex);
                //tmMcMoneyOffRuleInfo = tmMcMoneyOffRuleInfoList1.stream().max(Comparator.comparing(TMMcMoneyOffRuleInfo::getRuleIndex)).get();
                //rglog.info("订单金额<{}>满足法人机构<{}>的减免类营销活动<{}>的第<{}>档规则,继续校验后续信息!", mcMoneyOffTxnData.getOrderAmt(), globalInstId, mcNo, tmMcMoneyOffRuleInfo.getRuleIndex());
            }
            if (null != paymentOrderMoneyOffInfoBeanList && !paymentOrderMoneyOffInfoBeanList.isEmpty()) {
                //接口上送了使用指定活动指定规则进行优惠  如果该规则不满足优惠则不给予优惠
                rglog.info("使用指定活动<{}>指定规则<{}>进行优惠", mcNo, paymentOrderMoneyOffInfoBeanList.get(0).getRuleIndex());
                tmMcMoneyOffRuleInfoList1 = tmMcMoneyOffRuleInfoList1.stream().filter(item -> item.getRuleIndex().equals(paymentOrderMoneyOffInfoBeanList.get(0).getRuleIndex())).collect(Collectors.toList());
            }
            /* 减免类营销活动金额数据实体类赋值 */
            MoneyOffAmountData moneyOffAmountData = new MoneyOffAmountData();
            moneyOffAmountData.setInstId(instId);
            moneyOffAmountData.setMcNo(mcNo);
            moneyOffAmountData.setMcType(mcType);
            moneyOffAmountData.setMoneyOffSettlementMethod(tmMcMoneyOffInfo.getBudgetRechargeMethod());

            moneyOffAmountData.setMchntNo(mchntNo);
            moneyOffAmountData.setMcStartDate(tmMcMoneyOffInfo.getMcStartDate());
            moneyOffAmountData.setMcEndDate(tmMcMoneyOffInfo.getMcEndDate());
            moneyOffAmountData.setMcStatus(tmMcMoneyOffInfo.getMcStatus());
            moneyOffAmountData.setMcLvlCd(tmMcMoneyOffInfo.getMcLvlCd());
            //循环判断满足优惠条件的规则
            for (TMMcMoneyOffRuleInfo tmMcMoneyOffRuleInfo : tmMcMoneyOffRuleInfoList1) {
                copyMoneyOffRuleInfoAmountData(tmMcMoneyOffRuleInfo, moneyOffAmountData);

                /* 根据营销活动类型计算营销活动补贴-规则上包下不包 */
                String subsidy = calculateMcDiscountAmount(mcMoneyOffTxnData, mcType, tmMcMoneyOffRuleInfo);
                moneyOffAmountData.setFloorAmt(mcMoneyOffTxnData.getFloorAmt());
                moneyOffAmountData.setCellingAmt(mcMoneyOffTxnData.getCellingAmt());
                if (null == subsidy) {
                    rglog.info("机构<{}>的营销活动<{}>减免金额计算失败,本营销活动不予优惠!", instId, mcNo);
                    rglog.info("订单金额<{}>不满足满足活动<{}>规则<{}>优惠条件", orderAmt, tmMcMoneyOffRuleInfo.getMcNo(), tmMcMoneyOffRuleInfo.getRuleIndex());
                    continue;
                } else {
                    //如果优惠金额等于订单金额 减去0.01
                    if (subsidy.equals(mcMoneyOffTxnData.getOrderAmt())) {
                        rglog.info("订单金额<{}>与优惠金额<{}>相等，要求订单最少支付0.01元(优惠金额减去0.01元)");
                        BigDecimal subsidys = new BigDecimal(subsidy);
                        double minAmt = 0.01;
                        BigDecimal deductedAmount = BigDecimal.valueOf(minAmt);
                        subsidy = subsidys.subtract(deductedAmount).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
                        moneyOffAmountData.setTotalSubsidy(subsidy);
                    } else {
                        moneyOffAmountData.setTotalSubsidy(subsidy);
                    }
                }
                rglog.info("计算后法人机构<{}>的营销活动<{}>减免金额为<{}>", instId, mcNo, moneyOffAmountData.getTotalSubsidy());

                McSubsidyData mcSubsidyData = new McSubsidyData();
                mcSubsidyData.setTotalSubsidy(subsidy);
                mcSubsidyData.setSponsor(tmMcMoneyOffInfo.getSponsor());
                if (CommonConstant.SPONSOR_MIXED.equals(tmMcMoneyOffInfo.getSponsor())) {
                    mcSubsidyData.setBudget(tmMcMoneyOffInfo.getBudget());
                    mcSubsidyData.setBankBudget(tmMcMoneyOffInfo.getBankBudget());
                    mcSubsidyData.setExpectMchntQty(tmMcMoneyOffInfo.getExpectMchntQty());
                    mcSubsidyData.setBankBudgetRatio(tmMcMoneyOffInfo.getBankBudgetRatio());
                }
                mcSubsidyData.setMcType(mcType);

                /* 计算银行和商户出资比例 */
                retCode = calculateBankAndMchntSubsidyRatio(mcSubsidyData);
                if (CommonConstant.PROCESS_FAILED == retCode) {
                    rglog.info("机构<{}>的营销活动<{}>计算银行补贴金额和商户补贴金额失败,本营销活动不予优惠!", instId, mcNo);
                    rglog.info("订单金额<{}>不满足满足活动<{}>规则<{}>优惠条件", orderAmt, tmMcMoneyOffRuleInfo.getMcNo(), tmMcMoneyOffRuleInfo.getRuleIndex());
                    continue;
                }

                rglog.info("计算后,法人机构<{}>的营销活动<{}>的总减免金额为<{}>, 银行补贴金额为<{}>, 商户补贴金额为<{}>", instId, mcNo,
                        mcSubsidyData.getTotalSubsidy(), mcSubsidyData.getBankSubsidy(), mcSubsidyData.getMchntSubsidy());

                moneyOffAmountData.setBankSubsidy(mcSubsidyData.getBankSubsidy());
                moneyOffAmountData.setMchntSubsidy(mcSubsidyData.getMchntSubsidy());
                if (CommonConstant.SPONSOR_MIXED.equals(tmMcMoneyOffInfo.getSponsor())) {
                    moneyOffAmountData.setBankDiscountLimitAmt(mcSubsidyData.getBankDiscountLimitAmt());
                    moneyOffAmountData.setMchntDiscountLimitAmt(mcSubsidyData.getMchntDiscountLimitAmt());
                }

                //设置营销活动出资方
                moneyOffAmountData.setSponsor(tmMcMoneyOffInfo.getSponsor());
                /* 获取交易额度上限 */
                retCode = fetchAllQuotaData(moneyOffAmountData);
                if (CommonConstant.PROCESS_FAILED == retCode) {
                    rglog.info("获取机构<{}>的营销活动<{}>各维度限额和额度失败,本营销活动不予优惠!", instId, mcNo);
                    rglog.info("订单金额<{}>不满足满足活动<{}>规则<{}>优惠条件", orderAmt, tmMcMoneyOffRuleInfo.getMcNo(), tmMcMoneyOffRuleInfo.getRuleIndex());
                    continue;
                }

                /* 判断交易额度上限 */
                retCode = checkAllQuotaWithMcType(tmMcMoneyOffInfo, moneyOffAmountData);
                if (CommonConstant.PROCESS_FAILED == retCode) {
                    rglog.info("机构<{}>的营销活动<{}>判断各维度限额和额度失败,本营销活动不予优惠!", instId, mcNo);
                    rglog.info("订单金额<{}>不满足满足活动<{}>规则<{}>优惠条件", orderAmt, tmMcMoneyOffRuleInfo.getMcNo(), tmMcMoneyOffRuleInfo.getRuleIndex());
                    continue;
                }

                /* 本商户本营销活动最终优惠金额 */
                moneyOffAmountDataList.add(moneyOffAmountData);
                rglog.info("订单金额<{}>满足活动<{}>规则<{}>优惠条件", orderAmt, tmMcMoneyOffRuleInfo.getMcNo(), tmMcMoneyOffRuleInfo.getRuleIndex());
                break;
            }
        }

        rglog.info("--------------------------------------------------------------------");
        /* 取优惠金额最高的营销活动的数据 */
        if (!moneyOffAmountDataList.isEmpty()) {
            rglog.info("商户 <{}> 共有 <{}> 个减免类营销活动完成优惠金额计算,继续获取最优的活动来使用", mchntNo, moneyOffAmountDataList.size());

            //优先返回测试中的活动
            List<MoneyOffAmountData> testMoneyOffAmountDataList = moneyOffAmountDataList.stream().filter(item -> item.getMcStatus().equals(McStatusEnum.TESTING.getMcStatusCode())).collect(Collectors.toList());
            if (testMoneyOffAmountDataList.size() > 0) {
                rglog.info("优先返回该商户匹配的测试中的营销活动");
                BigDecimal tmpBigDecimal = testMoneyOffAmountDataList.stream().map(MoneyOffAmountData::getTotalSubsidyAmt).max(BigDecimal::compareTo).get();
                MoneyOffAmountData moneyOffAmountData = testMoneyOffAmountDataList.stream().filter(item -> (CommonConstant.ZERO == tmpBigDecimal.compareTo(item.getTotalSubsidyAmt()))).collect(Collectors.toList()).get(CommonConstant.ZERO);
                rglog.info("法人机构<{}>的商户号<{}>筛选出的优惠金额最高的优惠活动是<{}>, 优惠金额是<{}>", moneyOffAmountData.getInstId(),
                        moneyOffAmountData.getMchntNo(), moneyOffAmountData.getMcNo(), moneyOffAmountData.getTotalSubsidy());
                copyMoneyOffMcDiscountInfo(moneyOffAmountData, mcMoneyOffTxnData);
            } else {
                MoneyOffAmountData moneyOffAmountData = new MoneyOffAmountData();
                rglog.info("判断是否存在商户级、行级活动");
                List<MoneyOffAmountData> mchntMoneyOffAmountDataList = moneyOffAmountDataList.stream().filter(item -> item.getMcLvlCd().equals(CommonConstant.MC_LVL_CD_MCHNT)).collect(Collectors.toList());
                List<MoneyOffAmountData> bankMoneyOffAmountDataList = moneyOffAmountDataList.stream().filter(item -> item.getMcLvlCd().equals(CommonConstant.MC_LVL_CD_BANK)).collect(Collectors.toList());
                if (mchntMoneyOffAmountDataList.size() > 0) {
                    rglog.info("存在商户级活动，优先返回商户级优惠最高的活动");
                    BigDecimal tmpBigDecimal = mchntMoneyOffAmountDataList.stream().map(MoneyOffAmountData::getTotalSubsidyAmt).max(BigDecimal::compareTo).get();
                    moneyOffAmountData = mchntMoneyOffAmountDataList.stream().filter(item -> (CommonConstant.ZERO == tmpBigDecimal.compareTo(item.getTotalSubsidyAmt()))).collect(Collectors.toList()).get(CommonConstant.ZERO);
                } else if (bankMoneyOffAmountDataList.size() > 0) {
                    rglog.info("存在银行级活动，优先返回银行级优惠最高的活动");
                    BigDecimal tmpBigDecimal = bankMoneyOffAmountDataList.stream().map(MoneyOffAmountData::getTotalSubsidyAmt).max(BigDecimal::compareTo).get();
                    moneyOffAmountData = bankMoneyOffAmountDataList.stream().filter(item -> (CommonConstant.ZERO == tmpBigDecimal.compareTo(item.getTotalSubsidyAmt()))).collect(Collectors.toList()).get(CommonConstant.ZERO);

                } else {
                    BigDecimal tmpBigDecimal = moneyOffAmountDataList.stream().map(MoneyOffAmountData::getTotalSubsidyAmt).max(BigDecimal::compareTo).get();
                    moneyOffAmountData = moneyOffAmountDataList.stream().filter(item -> (CommonConstant.ZERO == tmpBigDecimal.compareTo(item.getTotalSubsidyAmt()))).collect(Collectors.toList()).get(CommonConstant.ZERO);
                }
                rglog.info("法人机构<{}>的商户号<{}>筛选出的优惠金额最高的优惠活动是<{}>, 优惠金额是<{}>", moneyOffAmountData.getInstId(),
                        moneyOffAmountData.getMchntNo(), moneyOffAmountData.getMcNo(), moneyOffAmountData.getTotalSubsidy());
                copyMoneyOffMcDiscountInfo(moneyOffAmountData, mcMoneyOffTxnData);
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }


    /**
     * 检查商户参加营销活动标准
     *
     * @param mcMchntFeeDiscountTxnData (合并)支付使用商户手续费优惠类营销活动交易信息
     * @param mchntBaseInfo             商户基本信息表T_B_MCHNT_BASE_INFO
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 16:54
     */
    private int checkMchntFeeDiscountMcPrerequisiteInfo(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData, TBMchntBaseInfo mchntBaseInfo) throws Exception {

        int returnCode;
        String instId = globalInstId;
        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();

        //商户基本信息存储到mcMchntFeeDiscountTransData中
        copyMchntBaseInfo(mcMchntFeeDiscountTxnData, mchntBaseInfo);
        //商户性质
        String mchntType = mchntBaseInfo.getMchntType();
        //独立营销活动标识
        String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
        //连锁商户号
        String chainMchntNo = mchntBaseInfo.getChainMchntNo();
        //是否独立维护商户资料
        String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
        if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
            rglog.info("商户<{}> 商户类型为11:连锁商户门店，商户独立营销活动标识为<{}> 是否独立维护商户资料<{}> 获取营销活动时需根据上级商户<{}> 获取!", mchntNo, idpdCmavyFlg, independentDataFlag, chainMchntNo);
            mchntNo = chainMchntNo;
            //查询上级商户的基本信息
            MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
            TBMchntBaseInfo chainMchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(instId, mchntNo);
            if (null == chainMchntBaseInfo) {
                //查询不到商户信息，流程结束
                rglog.error("查询当前商户<{}>的上级商户<{}>基本信息信息失败!", mchntBaseInfo.getMchntNo(), chainMchntNo);
                throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
            }
            //商户基本信息存储到mcMchntFeeDiscountTransData中
            copyMchntBaseInfo(mcMchntFeeDiscountTxnData, chainMchntBaseInfo);
        } else {
            rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}> 无需判断独立营销活动标识，均使用当前商户号计算营销！", mchntBaseInfo.getMchntNo(), independentDataFlag, mchntType);
        }

        //判断机构是否限定了商户结算账户是对公户的商户不允许参加营销活动
        MompSysParamMapper mompSysParamMapper = new MompSysParamMapperImpl();
        SysParam sysParam = mompSysParamMapper.getSysParamInfoBuyPrimaryKey(globalInstId, MOMP_DIFFERENTIATE_SETTLEACCTTYPE, MOMP_DIFFERENTIATE_SETTLEACCTTYPE);
        if (null != sysParam) {
            //判断设置的标志位是限制对公户不能参加，还是不限制对公户不能参加
            String paramValue = sysParam.getParamValue();
            if (CommonConstant.YES.equals(paramValue)) {
                //如果限定了，则查询商户的结算账户
                rglog.info("机构<{}>限定了结算账户为对公户的商户不允许参加手续费营销活动，继续判断商户<{}> 的结算账户信息!", instId, mchntNo);
                /*商户结算信息正式表*/
                McMchntAcctInfoMapper mcMchntAcctInfoMapper = new McMchntAcctInfoMapperImpl();
                MchntAcctInfo mchntAcctInfo = mcMchntAcctInfoMapper.selectMchntAcctInfoByPrimaryKey(globalInstId, mchntNo, "*", FundTypeEnum.SETTLE_TYPE.getFundCode());
                if (null != mchntAcctInfo) {
                    //结算账户类型
                    String settleAcctType = mchntAcctInfo.getSettleAcctType();
                    if (AcctTypeEnum.OWN_CORPORATE_ACCOUNT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OTHER_CORPORATE_ACCOUNT.getAcctType().equals(settleAcctType)) {
                        //本商户的结算账户为对公户，不允许参加活动
                        rglog.error("商户<{}> 结算账户类型<{}> 机构设置了结算账户为对公户的商户不允许参加手续费营销活动，故此商户不允许参加此活动!", instId, settleAcctType);
                        return CommonConstant.PROCESS_FAILED;
                    }
                } else {
                    rglog.error("商户<{}> 未获取到结算账号信息，异常!", mchntNo);
                    return CommonConstant.PROCESS_FAILED;
                }
            }
        }

        String feeInputMode = mcMchntFeeDiscountTxnData.getFeeInputMode();
        //当上送的手续费收取方式不是使用现有费率时判断
        if (!CommonConstant.FEE_MODE_LADDER.equals(feeInputMode))
            /* 判断是否存在免充值的对客营销活动，如果存在，需要重新计算应收手续费及商户清算金额字段 */
            checkIsExisNoRechargeToClientMc(mcMchntFeeDiscountTxnData, mchntBaseInfo);

        /* 使用商户号匹配商户手续费优惠营销活动信息 */
        returnCode = matchMchntFeeDiscountMchntPrerequsite(mcMchntFeeDiscountTxnData, mchntBaseInfo);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("机构<{}>的商户<{}>未参加任何商户手续费优惠营销活动,或已退出正在进行中的营销活动!", instId, mchntNo);
            return CommonConstant.PROCESS_FAILED;
        }

        String mcNo = mcMchntFeeDiscountTxnData.getMcNo();

        /* 手续费减免达标数据统计表中记录的商户当前是新增商户还是存量商户标志 */
        String newMchntFlag = mcMchntFeeDiscountTxnData.getNewMchntCriteriaFlag();

        /* 取营销活动基本信息 */
        rglog.info("获取营销活动<{}>基本信息", mcNo);
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = getMchntFeeDiscountMcInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("机构<{}>的商户<{}>未获取到商户手续费优惠营销活动信息!", instId, mchntNo);
            return CommonConstant.PROCESS_FAILED;
        }
        convertMchntFeeDiscountMcInfo(tmMcMchntFeeDiscountInfo, mcMchntFeeDiscountTxnData);
        String mcType = tmMcMchntFeeDiscountInfo.getMcType();

        if (CommonConstant.FEE_POSTPONE_DISCOUNT_FLAG.equals(tmMcMchntFeeDiscountInfo.getAfterFlag()) && CommonConstant.MCHNT_OLD_FLAG.equals(newMchntFlag)) {
            /* 存量商户-达标后手续费优惠规则-达标后的交易通过返现营销的不在联机计算手续费优惠 */
            rglog.info("存量商户-达标后手续费优惠规则-达标后的交易通过返现营销的不在联机计算手续费优惠,营销活动<{}>", mcNo);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 判断是否支持支付产品 */
        rglog.info("获取营销活动<{}>支付产品信息", mcNo);
        returnCode = checkMompProductSupportInfo(instId, mcNo, mcMchntFeeDiscountTxnData.getBizProdCode());
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("机构<{}>的营销活动<{}>不支持营销产品<{}>", instId, mcNo, mcMchntFeeDiscountTxnData.getBizProdCode());
            return CommonConstant.PROCESS_FAILED;
        }

        /* 存量商户取营销活动规则,新增商户直接手续费全免 */
        if (CommonConstant.MCHNT_OLD_FLAG.equals(newMchntFlag)) {

            /* 针对存量商户检查营销活动状态 */
            returnCode = checkMcStatus(mcMchntFeeDiscountTxnData);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("机构<{}>的减免类营销活动<{}>信息校验失败! RETURN_CODE=<{}>", instId, mcNo);
                return CommonConstant.PROCESS_FAILED;
            }

            /* 存量商户取营销活动规则信息场景 */
            rglog.debug("CRITERIA_VALUE=<{}>", mcMchntFeeDiscountTxnData.getCriteriaValue());
            List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList = getMchntFeeDiscountMcRuleInfo(instId, mcNo);
            if (null == tmMcMchntFeeDiscountRuleInfoList || tmMcMchntFeeDiscountRuleInfoList.isEmpty()) {
                /* 未取到营销活动规则信息,本营销活动不可以优惠! */
                rglog.info("获取机构<{}>的营销活动<{}>优惠规则信息匹配失败,本营销活动不予优惠!", instId, mcNo);
                return CommonConstant.PROCESS_FAILED;
            }

            /* 代码判断匹配到了哪条规则上 */
            TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo;
            BigDecimal criteriaValue = new BigDecimal(mcMchntFeeDiscountTxnData.getCriteriaValue()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList1 = new ArrayList<>();
            for (TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo1 : tmMcMchntFeeDiscountRuleInfoList) {

                BigDecimal floor = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaFloor()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                /* 按照左包右不包原则判断 */
                if (CommonConstant.ZERO <= criteriaValue.compareTo(floor) && CommonConstant.ZERO > criteriaValue.compareTo(celling)) {
                    tmMcMchntFeeDiscountRuleInfoList1.add(tmMcMchntFeeDiscountRuleInfo1);
                }
            }

            if (tmMcMchntFeeDiscountRuleInfoList1.isEmpty()) {
                rglog.info("获取机构<{}>的营销活动<{}>优惠规则信息匹配失败,无满足条件的规则,本营销活动不予优惠!", instId, mcNo);
                return CommonConstant.PROCESS_FAILED;
            } else {
                rglog.info("当前商户<{}>,营销活动<{}>符合的规则条数为<{}>,如果多余一条，则取规则号最大的!", mchntNo, mcNo, tmMcMchntFeeDiscountRuleInfoList1.size());
                if (CommonConstant.ONE != tmMcMchntFeeDiscountRuleInfoList1.size()) {
                    /* 超过1条以上规则符合条件 */
                    tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.stream().max(Comparator.comparing(TMMcMchntFeeDiscountRuleInfo::getRuleIndex)).get();
                } else {
                    tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.get(CommonConstant.ZERO);
                }
            }

            convertMchntFeeDiscountMcRuleInfo(tmMcMchntFeeDiscountRuleInfo, mcMchntFeeDiscountTxnData);

            if (null != mcMchntFeeDiscountTxnData.getMrctDisUpLmtVal() && !"".equals(mcMchntFeeDiscountTxnData.getMrctDisUpLmtVal())) {
                rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mcMchntFeeDiscountTxnData.getMrctDisUpLmtVal());
                mcMchntFeeDiscountTxnData.setDiscountLimit(mcMchntFeeDiscountTxnData.getMrctDisUpLmtVal());
            } else {
                /* 根据营销活动规则计算商户当前优惠限额 */
                if (FeeCalTypeEnum.TYPE_0.getRuleType().equals(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo())) {
                    /* 无需取优惠限额的计算规则,直接使用最大值 */
                    mcMchntFeeDiscountTxnData.setDiscountLimit(CommonConstant.BIG_NUMBER);

                } else if (FeeCalTypeEnum.TYPE_1.getRuleType().equals(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo()) ||
                        FeeCalTypeEnum.TYPE_13.getRuleType().equals(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo())) {
                    /* 无需取优惠限额的计算规则,直接使用规则中的限额 */
                    mcMchntFeeDiscountTxnData.setDiscountLimit(tmMcMchntFeeDiscountRuleInfo.getDiscountLimit());

                } else {
                    TMPlatCalRule tmPlatCalRule = selectCalculationRuleInfoByPK(instId, tmMcMchntFeeDiscountRuleInfo.getCalRuleNo());
                    if (null == tmPlatCalRule) {
                        /* 未取到营销活动规则信息,本营销活动不可以优惠! */
                        rglog.info("获取机构<{}>的营销活动<{}>的优惠规则<{}>的计算规则<{}>信息匹配,本营销活动不予优惠!",
                                instId, mcNo, tmMcMchntFeeDiscountRuleInfo.getRuleIndex(), tmMcMchntFeeDiscountRuleInfo.getCalRuleNo());
                        return CommonConstant.PROCESS_FAILED;
                    }

                    convertMchntFeeDiscountMcCalRuleInfo(tmPlatCalRule, mcMchntFeeDiscountTxnData);
                    calculateMchntFeeDiscountLimit(mcMchntFeeDiscountTxnData);
                }
            }

            rglog.info("商户<{}>的商户手续费优惠营销活动<{}>的规则<{}>优惠限额为<{}>", mchntNo, mcNo, mcMchntFeeDiscountTxnData.getRuleIndex(), mcMchntFeeDiscountTxnData.getDiscountLimit());

            /* 根据营销活动类型计算商户手续费优惠营销活动手续费优惠金额和实收手续费金额 */
            String subsidy = calculateMcDiscountAmount(mcMchntFeeDiscountTxnData, mcType, tmMcMchntFeeDiscountRuleInfo);
            if (null == subsidy) {
                rglog.info("机构<{}>的营销活动<{}>手续费优惠金额计算失败,本营销活动不予优惠!", instId, mcNo);
                return CommonConstant.PROCESS_FAILED;
            } else {
                BigDecimal zeroAmt = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal totalSubsidy = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeDiscount()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                if (CommonConstant.ZERO == zeroAmt.compareTo(totalSubsidy)) {
                    /* 优惠金额为0,不优惠商户手续费 */
                    rglog.info("商户优惠手续费为0元,无手续费优惠!");
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("机构<{}>的商户的<{}>的商户手续费优惠营销活动<{}>的减免金额<{}>,实收手续费<{}>", instId, mchntNo, mcNo, mcMchntFeeDiscountTxnData.getMchntFeeDiscount(), mcMchntFeeDiscountTxnData.getMchntFeeActual());
                }
            }

            /* 获取交易额度上限 */
            returnCode = fetchAllQuotaData(mcMchntFeeDiscountTxnData);
            if (CommonConstant.PROCESS_FAILED == returnCode) {
                rglog.info("获取机构<{}>的营销活动<{}>各维度限额和额度失败,本营销活动不予优惠!", instId, mcNo);
                return CommonConstant.PROCESS_FAILED;
            }

            /* 判断交易额度上限 */
            returnCode = checkAllQuotaWithMcType(mcMchntFeeDiscountTxnData, mcMchntFeeDiscountTxnData);
            if (CommonConstant.PROCESS_FAILED == returnCode) {
                rglog.info("机构<{}>的营销活动<{}>判断各维度限额和额度失败,本营销活动不予优惠!", instId, mcNo);
                return CommonConstant.PROCESS_FAILED;
            }
            /* 限额检查完毕,后续业务处理 */
            rglog.info("机构<{}>的营销活动<{}>的商户<{}>的手续费优惠限额检查完毕!开始后续业务流程!", instId, mcNo, mchntNo);

        } else {
            /* 新增商户场景 */

            //如果是特殊费率商户，则没有任何手续费优惠
            if (CommonConstant.FEE_MODE_LADDER.equals(mcMchntFeeDiscountTxnData.getFeeInputMode())) {
                mcMchntFeeDiscountTxnData.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT_FEE);
                mcMchntFeeDiscountTxnData.setMchntFeeActual(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
                rglog.info("商户<{}>的手续费收取方式为  使用现有费率，无手续费优惠", mchntNo);
                return CommonConstant.PROCESS_SUCCESS;
            }

            /* 新增商户无须检查营销活动状态,走到这一步的肯定是可以有优惠的,而且此时营销活动可能已经结束了,但是新增商户还是要给优惠的 */
            if (CommonConstant.PROCESS_SUCCESS != checkNewMchntMcStatus(mcMchntFeeDiscountTxnData)) {
                rglog.error("机构<{}>的手续费优惠营销活动<{}>信息校验失败! RETURN_CODE=<{}>", instId, mcNo);
                return CommonConstant.PROCESS_FAILED;
            }
            //设置实收手续费金额
            mcMchntFeeDiscountTxnData.setMchntFeeActual(BigDecimal.ZERO.toString());
            //设置手续费优惠金额
            mcMchntFeeDiscountTxnData.setMchntFeeDiscount(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
            //设置新商户规则编号为 0
            mcMchntFeeDiscountTxnData.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

            rglog.info("机构<{}>的商户<{}>的营销活动<{}>开始计算新增商户手续费优惠值...", instId, mchntNo, mcNo);
            int getFeeDiscountResult = getNewMchntFeeDiscount(mcMchntFeeDiscountTxnData);
            //0:成功，流程继续  1:本次结束，继续下一次
            if (CommonConstant.ONE == getFeeDiscountResult) {
                //记录本订单明细没有手续费优惠，添加到返回列表
                return CommonConstant.PROCESS_FAILED;
            }

            String newMchntAmountLimit = mcMchntFeeDiscountTxnData.getNewMchntAmountLimit();
            /* 控制下限-0 */
            mcMchntFeeDiscountTxnData.setCriteriaFloor(CommonConstant.ZERO_AMOUNT);
            /* 控制上限-无限大 */
            mcMchntFeeDiscountTxnData.setCriteriaCelling(newMchntAmountLimit);
            /* 优惠周期-按月 */
            mcMchntFeeDiscountTxnData.setDiscountPeriod(CommonConstant.MFD_PERIOD_MONTH);
            /* 优惠类型-免手续费 */
            mcMchntFeeDiscountTxnData.setDiscountType(CommonConstant.MCHNT_FEE_FREE);
            /* 优惠力度 */
            mcMchntFeeDiscountTxnData.setDiscount(CommonConstant.MCHNT_FEE_FREE);
            /* 计算规则编号 */
            mcMchntFeeDiscountTxnData.setCalRuleNo(FeeCalTypeEnum.TYPE_0.getRuleType());
            /* 优惠上限 */
            mcMchntFeeDiscountTxnData.setDiscountLimit(newMchntAmountLimit);

            rglog.info("商户<{}>的商户手续费优惠营销活动<{}>的规则<{}>优惠限额为<{}>", mchntNo, mcNo, mcMchntFeeDiscountTxnData.getRuleIndex(), mcMchntFeeDiscountTxnData.getDiscountLimit());
            /* 限额检查完毕,后续业务处理 */
            rglog.info("机构<{}>的营销活动<{}>的商户<{}>的手续费优惠限额检查完毕!开始后续业务流程!", instId, mcNo, mchntNo);
        }

        return CommonConstant.PROCESS_SUCCESS;
    }


    /**
     * 检查商户是否已参加商户手续费优惠营销活动
     *
     * @param mcMchntFeeDiscountTxnData (合并)支付使用商户手续费优惠类营销活动交易信息
     * @param mchntBaseInfo             商户基本信息表T_B_MCHNT_BASE_INFO
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 11:46
     */
    private int matchMchntFeeDiscountMchntPrerequsite(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData, TBMchntBaseInfo mchntBaseInfo) throws Exception {

        String instId = mchntBaseInfo.getInstId();
        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();
        String transDate = mcMchntFeeDiscountTxnData.getTransDate();


        /* 查询商户手续费减免达标数据统计表数据,看是否商户已经存在表中 */
        TMStatMfdCriteria tmStatMfdCriteria = selectTMStatMfdCriteriaByUsingMchntNoAndDateRange(instId, mchntNo, transDate);
        if (null == tmStatMfdCriteria) {
            rglog.info("未找到机构<{}>的商户<{}>当前统计周期的商户手续费优惠活动统计数据,需进一步判断商户是否是新增商户!", instId, mchntNo);

            String orgId = mchntBaseInfo.getSignInstId();

            /* 查询营销活动机构表,判断是否存在当前商户管理机构 */
            MfdMcListInfoInObj mfdMcListInfoInObj = new MfdMcListInfoInObj();
            mfdMcListInfoInObj.setInstId(globalInstId);
            mfdMcListInfoInObj.setOrgId(orgId);
            McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
            List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoList = mcDetailInfoMapper.selectMfdMcDetailInfoForComboPayment(mfdMcListInfoInObj);
            if (null == tmMcMchntFeeDiscountInfoList || tmMcMchntFeeDiscountInfoList.isEmpty()) {
                rglog.info("未获取到法人机构<{}>的商户<{}>所在机构<{}>的支持新增商户的商户手续费优惠类营销活动信息,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo, orgId);
                return CommonConstant.PROCESS_FAILED;
            }

            boolean notDistinguishMiddleOfMonth;
            //判断机构是否设置了区分新商户是15号之前还是之后入驻
            MompSysParamMapper mompSysParamMapper = new MompSysParamMapperImpl();
            SysParam sysParam = mompSysParamMapper.getSysParamInfoBuyPrimaryKey(globalInstId, MOMP_DISTINGUISH_MIDDLE_OF_MONTH, MOMP_DISTINGUISH_MIDDLE_OF_MONTH);
            //如果没有配置（为空）时或者配置的为区分15号时，则进行区分15号之前之后的处理
            if (null != sysParam && CommonConstant.NO.equals(sysParam.getParamValue())) {
                rglog.info("机构<{}>配置了新商户不区分15号之前之后入驻", globalInstId);
                notDistinguishMiddleOfMonth = true;
            } else {
                rglog.info("机构<{}> 新商户区分15号之前之后入驻", globalInstId);
                notDistinguishMiddleOfMonth = false;
            }

            String mchntExpandTime = mcMchntFeeDiscountTxnData.getMchntExpandTime();
            String mchntExpandDate = mchntExpandTime.substring(0, 4) + mchntExpandTime.substring(5, 7) + mchntExpandTime.substring(8, 10);

            List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoList1 = new ArrayList<>();

            /* 判断商户是否重复入网商户 */
            boolean repeatFlag = checkMchntRepeatFlag(mchntBaseInfo.getMchntNo(), mchntBaseInfo.getMchntExpandTime());
            if (repeatFlag) {
                rglog.info("法人机构<{}>的商户<{}>所在机构<{}>为重复入网商户,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo, orgId);
                return CommonConstant.ONE;
            }

            /* 判断商户入驻日期是否在营销活动期间 */
            for (TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo : tmMcMchntFeeDiscountInfoList) {

                /* 判断商户是否是在营销活动起止日期内入驻 */
                int returnCode = MompDateUtil.checkDateRange(mchntExpandDate, tmMcMchntFeeDiscountInfo.getMcStartDate(), tmMcMchntFeeDiscountInfo.getMcEndDate());
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.info("法人机构<{}>的商户<{}>的入驻日期<{}>并未在营销活动<{}>的起止日期<{}>~<{}>内,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo, mchntExpandDate, tmMcMchntFeeDiscountInfo.getMcNo(), tmMcMchntFeeDiscountInfo.getMcStartDate(), tmMcMchntFeeDiscountInfo.getMcEndDate());
                    continue;
                }

                /* 判断当前日期是否已超过该商户入驻日期+优惠月份数 */
                if (!checkNewMchntAvailability(mcMchntFeeDiscountTxnData.getMchntNo(), tmMcMchntFeeDiscountInfo, mchntExpandDate, notDistinguishMiddleOfMonth)) {
                    rglog.info("法人机构<{}>的商户<{}>的入驻日期<{}>并未在营销活动<{}>的起止日期<{}>~<{}>内,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo, mchntExpandDate, tmMcMchntFeeDiscountInfo.getMcNo(), tmMcMchntFeeDiscountInfo.getMcStartDate(), tmMcMchntFeeDiscountInfo.getMcEndDate());
                    continue;
                }

                /* 判断当前支持新增商户的活动是否指定了商圈，如果指定了商圈，判断当前商户是否在商圈中，如果不在，则当前商户不能参加当前新商户的营销活动 */
                //查询营销活动商户信息表，判断活动是否设置了限定了指定的商圈进行参加
                List<TMMcMchntInfo> tMMcMchntInfoList = selectMcMchntInfoListByMcNo(globalInstId, tmMcMchntFeeDiscountInfo.getMcNo(), CommonConstant.MCHNT_RANGE_TYPE_AREA);
                String mchntArea = mcMchntFeeDiscountTxnData.getMchntArea();

                if (null != tMMcMchntInfoList && !tMMcMchntInfoList.isEmpty()) {
                    for (TMMcMchntInfo tMMcMchntInfo : tMMcMchntInfoList) {
                        String mcMchntArea = tMMcMchntInfo.getMchntNo();
                        if (mcMchntArea.equals(mchntArea)) {
                            tmMcMchntFeeDiscountInfoList1.add(tmMcMchntFeeDiscountInfo);
                            rglog.info("营销活动<{}>限定了参与活动的商圈<{}>，当前商户所属商圈<{}>,当前活动允许参加!", tmMcMchntFeeDiscountInfo.getMcNo(), tMMcMchntInfo.getMchntNo(), mchntArea);
                        } else {
                            rglog.info("营销活动<{}>限定了参与活动的商圈<{}>，当前商户所属商圈<{}>,当前活动不允许当前商户参加!", tmMcMchntFeeDiscountInfo.getMcNo(), tMMcMchntInfo.getMchntNo(), mchntArea);
                        }
                    }
                } else {
                    //如果活动未指定参与的商圈，则任何新增商户都可参与
                    tmMcMchntFeeDiscountInfoList1.add(tmMcMchntFeeDiscountInfo);
                    rglog.info("营销活动<{}>未限定参与活动的商圈,当前商户可以参加当前活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                }
            }

            List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoAfterJudgeMchntNature = new ArrayList<>();
            /* 判断活动是否区分商户性质参加 */
            JudgeMcDiscriminateMchntNature(tmMcMchntFeeDiscountInfoList1, tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, mcMchntFeeDiscountTxnData);

            /* 选取支持手续费优惠时间最长的营销活动免手续费 */
            TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo;
            if (CommonConstant.ZERO < tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.size()) {
                //使用免手续费结束日期最晚的活动进行优惠（remark1中存储的是免手续费结束的日期）
                tmMcMchntFeeDiscountInfo = tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.stream().max(Comparator.comparing(TMMcMchntFeeDiscountInfo::getRemark1)).get();
            } else {
                rglog.info("法人机构<{}>的商户<{}>未找到适合的支持新增商户的营销活动,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo);
                return CommonConstant.PROCESS_FAILED;
            }

            /* 为新增商户计算商户手续费减免达标数据统计表中数据 */
            tmStatMfdCriteria = generateNewMchntCriteriaData(mchntNo, tmMcMchntFeeDiscountInfo, mchntExpandDate, notDistinguishMiddleOfMonth);
            if (null == tmStatMfdCriteria) {
                rglog.info("法人机构<{}>的商户<{}>的入住日期<{}>并未在营销活动<{}>的起止日期<{}>~<{}>内,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo, mchntExpandDate, tmMcMchntFeeDiscountInfo.getMcNo(), tmMcMchntFeeDiscountInfo.getMcStartDate(), tmMcMchntFeeDiscountInfo.getMcEndDate());
                return CommonConstant.PROCESS_FAILED;
            }

            //查询营销活动商户信息表，当前商户的活动是否存在营销活动信息表中，或所属商圈在营销活动信息表中，如果是，则无需登记营销活动商户信息表
            TBMchntBaseInfo queryMchntBaseInfo = new TBMchntBaseInfo();
            queryMchntBaseInfo.setInstId(instId);
            queryMchntBaseInfo.setMchntNo(mchntNo);
            queryMchntBaseInfo.setMchntArea(mcMchntFeeDiscountTxnData.getMchntArea());
            List<TMMcMchntInfo> tmMcMchntInfoList = matchMcMchntInfoByUsingMchntInfoAndMcNo(queryMchntBaseInfo, tmMcMchntFeeDiscountInfo.getMcNo());
            if (null == tmMcMchntInfoList || tmMcMchntInfoList.isEmpty()) {
                //为新增商户添加营销活动商户信息表数据
                GenerateTableDataService generateTableDataService = new GenerateTableDataService();
                mcMchntFeeDiscountTxnData.setMcNo(tmMcMchntFeeDiscountInfo.getMcNo());
                boolean generateTmMcMchntInfoResult = generateTableDataService.generateTmMcMchntInfoData(mcMchntFeeDiscountTxnData, rglog);
                if (!generateTmMcMchntInfoResult) {
                    rglog.info("法人机构<{}> 商户<{}> 营销活动<{}> 登记营销活动商户信息表数据失败!", globalInstId, mchntNo, tmStatMfdCriteria.getMcNo());
                    return CommonConstant.PROCESS_FAILED;
                }

                boolean generateTmPlatBizTmpMcMchntInfoResult = generateTableDataService.generateTmPlatBizTmpMcMchntInfoData(mcMchntFeeDiscountTxnData, rglog);
                if (!generateTmPlatBizTmpMcMchntInfoResult) {
                    rglog.info("法人机构<{}> 商户<{}> 营销活动<{}> 登记临时表营销活动商户信息数据失败!", globalInstId, mchntNo, tmStatMfdCriteria.getMcNo());
                    return CommonConstant.PROCESS_FAILED;
                }
            } else {
                rglog.info("使用商户号 <{}>,商圈 <{}>,营销活动编号<{}> 查询到营销活动商户信息表信息，无需再次登记营销活动商户信息表数据!", mchntNo, queryMchntBaseInfo.getMchntArea(), tmMcMchntFeeDiscountInfo.getMcNo());
            }
        } else {
            /* 成功取到商户手续费减免达标数据统计表数据,商户是存量商户或已登记商户,可以进行进一步分处理 */
            rglog.info("成功取到商户手续费减免达标数据统计表数据,商户新增标志<{}>(0:存量商户 1：新增商户),可以进一步进行处理", tmStatMfdCriteria.getNewMchntFlag());

            /* 判断商户优惠退出状态 */
            int exitStatus = checkMchntExitFlag(tmStatMfdCriteria.getExitDiscountStatus());
            if (CommonConstant.PROCESS_SUCCESS != exitStatus) {
                rglog.error("机构<{}>的商户<{}>在统计周期<{}>-<{}>期间已使用完所有手续费优惠额度,已退出优惠!",
                        instId, mchntNo, tmStatMfdCriteria.getPeriodStartDate(), tmStatMfdCriteria.getPeriodEndDate());
                return CommonConstant.PROCESS_FAILED;
            }

            /* 判断商户达标状态 */
            if (!StringUtil.isNullorEmpty(tmStatMfdCriteria.getCriteriaFlag())) {
                int criteriaFlag = checkStockMchntCriteriaFlag(tmStatMfdCriteria.getCriteriaFlag());
                if (CommonConstant.PROCESS_SUCCESS != criteriaFlag) {
                    rglog.error("机构<{}>的商户<{}>在统计周期<{}>-<{}>期间未满足达标条件,不可优惠!",
                            instId, mchntNo, tmStatMfdCriteria.getPeriodStartDate(), tmStatMfdCriteria.getPeriodEndDate());
                    return CommonConstant.PROCESS_FAILED;
                }
            }
        }

        convertMchntFeeDiscountCriteria(tmStatMfdCriteria, mcMchntFeeDiscountTxnData);

        return CommonConstant.PROCESS_SUCCESS;
    }


    /**
     * 使用营销活动商户信息对象获取营销活动基本信息
     *
     * @param tmMcMchntInfo        营销活动商户信息表
     * @param tmMcMoneyOffInfoList 减免类营销活动信息表
     * @author Jinan Liu
     * @since 2020/4/14 09:44
     */
    private void getMoneyOffMcInfo(TMMcMchntInfo tmMcMchntInfo, List<TMMcMoneyOffInfo> tmMcMoneyOffInfoList) {

        String instId = tmMcMchntInfo.getInstId();
        String mcNo = tmMcMchntInfo.getMcNo();

        try {
            /* 根据营销活动状态查询营销活动信息,必须是进行中或测试中的营销活动才可以查询到 */
            McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
            TMMcMoneyOffInfo mcMoneyOffInfo = mcDetailInfoMapper.selectMoMcDetailInfoByMcStatus(instId, mcNo, McStatusEnum.PROGRESSING.getMcStatusCode());
            if (null == mcMoneyOffInfo) {
                rglog.error("机构<{}>的减免类营销活动<{}>信息查询失败!", instId, mcNo);
            } else {
                if (tmMcMchntInfo.getExitFlag().equals(CommonConstant.MC_NOT_EXIT_FLAG) && tmMcMchntInfo.getNewMchntFlag().equals(CommonConstant.MCHNT_OLD_FLAG) ||
                        tmMcMchntInfo.getExitFlag().equals(CommonConstant.MC_NOT_EXIT_FLAG) && tmMcMchntInfo.getNewMchntFlag().equals(CommonConstant.MCHNT_NEW_FLAG)) {
                    tmMcMoneyOffInfoList.add(mcMoneyOffInfo);
                } else {
                    rglog.info("法人机构<{}>的商户<{}>未参加减免类营销活动<{}>!NEW_MCHNT_FLAG<{}>,EXIT_FLAG<{}>", globalInstId, tmMcMchntInfo.getMchntNo(), mcNo, tmMcMchntInfo.getNewMchntFlag(), tmMcMchntInfo.getExitFlag());
                }
            }
        } catch (Exception e) {
            rglog.error("机构<{}>的减免类营销活动<{}>信息查询失败!", instId, mcNo);
        }
    }

    /**
     * 使用营销活动商户信息对象获取商户手续费优惠类营销活动基本信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountInfo 商户手续费减免类营销活动信息表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 14:14
     */
    private TMMcMchntFeeDiscountInfo getMchntFeeDiscountMcInfo(String instId, String mcNo) throws Exception {

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.selectMchntFeeDiscountMcDetailInfo(instId, mcNo);
    }

    /**
     * 检查营销活动状态
     * 商户手续费优惠类营销活动同时检查存量商户对应的当前交易日期是否在营销活动时间范围内
     *
     * @param object 数据入参对象
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/14 10:00
     */
    private int checkMcStatus(Object object) {

        String instId;
        String mcStatus;
        String mcNo;
        String mcStartDate;
        String mcEndDate;
        String mchntNo = "";

        if (object instanceof TMMcMoneyOffInfo) {
            /* 减免类营销活动 */
            instId = ((TMMcMoneyOffInfo) object).getInstId();
            mcStatus = ((TMMcMoneyOffInfo) object).getMcStatus();
            mcStartDate = ((TMMcMoneyOffInfo) object).getMcStartDate();
            mcEndDate = ((TMMcMoneyOffInfo) object).getMcEndDate();
            mcNo = ((TMMcMoneyOffInfo) object).getMcNo();

        } else if (object instanceof McMchntFeeDiscountTxnData) {
            /* 商户手续费优惠类营销活动 */
            instId = ((McMchntFeeDiscountTxnData) object).getInstId();
            mcStatus = ((McMchntFeeDiscountTxnData) object).getMcStatus();
            mcStartDate = ((McMchntFeeDiscountTxnData) object).getMcStartDate();
            mcEndDate = ((McMchntFeeDiscountTxnData) object).getMcEndDate();
            mcNo = ((McMchntFeeDiscountTxnData) object).getMcNo();
            mchntNo = ((McMchntFeeDiscountTxnData) object).getMchntNo();

        } else {
            rglog.error("不支持的对象类型<{}>", object.getClass());
            return CommonConstant.PROCESS_FAILED;
        }

        /* 判断营销活动状态是否是进行中 */
        if (!McStatusEnum.PROGRESSING.getMcStatusCode().equals(mcStatus) && !McStatusEnum.TESTING.getMcStatusCode().equals(mcStatus)) {
            rglog.error("{}, INST_ID=<{}>, MC_NO=<{}>, MC_STATUS=<{}>",
                    RespCodeEnum.WRONG_MC_STATUS_TO_DISCOUNT_ERROR.getRespDesc(), instId, mcNo, mcStatus);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 检查商户手续费优惠累营销活动存量商户对应营销活动时间 */
        int returnCode = MompDateUtil.checkDateRange(globalTxnDate, mcStartDate, mcEndDate);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("当前交易日期<{}>未在营销活动的有效期<{}>-<{}>内,机构<{}>的存量商户<{}>不可参加营销活动<{}>",
                    globalTxnDate, mcStartDate, mcEndDate, instId, mchntNo, mcNo);
            return CommonConstant.PROCESS_FAILED;
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 判断当前营销活动是否支持当前交易类型
     * 查询到数据返回0
     * 未查询到数据返回-1
     *
     * @param instId      法人机构号
     * @param mcNo        营销活动编号
     * @param bizProdCode 支付产品类型
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 16:20
     */
    private int checkMompProductSupportInfo(String instId, String mcNo, String bizProdCode) throws Exception {

        McProductInfoMapper mcProductInfoMapper = new McProductInfoMapperImpl();

        if (null == mcProductInfoMapper.selectMcProductInfoByPrimaryKey(instId, mcNo, bizProdCode)) {
            rglog.error("机构<{}>的营销活动<{}>不支持营销产品<{}>", instId, mcNo, bizProdCode);
            return CommonConstant.PROCESS_FAILED;
        } else {
            return CommonConstant.PROCESS_SUCCESS;
        }
    }

    /**
     * 使用营销活动编号查询营销活动所有时间规则信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return java.util.List<cc.rengu.igas.momp.common.entity.TMMcTimeInfo> 营销活动时间信息表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/14 11:35
     */
    private List<TMMcTimeInfo> getAllMcTimeListInfo(String instId, String mcNo) throws Exception {

        McTimeInfoMapper mcTimeInfoMapper = new McTimeInfoMapperImpl();
        return mcTimeInfoMapper.selectMcTimeInfoList(instId, mcNo);
    }

    /**
     * 检查当前时间是否在营销活动允许时间范围内
     * 在时间范围内返回0
     * 不在时间范围内返回-1
     *
     * @param transDate        当前交易日期
     * @param transTime        当前交易时间
     * @param tmMcTimeInfoList 营销活动时间信息表
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/14 14:34
     */
    private int checkMcTimeInfo(String transDate, String transTime, List<TMMcTimeInfo> tmMcTimeInfoList) {

        int returnCode;
        int matchFlag = CommonConstant.FLAG_NOT_SET;
        /* 获取当前日期对应星期几 */
        MompDateUtil mompDateUtils = new MompDateUtil();
        int dayOfWeek = mompDateUtils.getWeek(transDate);

        for (TMMcTimeInfo tmMcTimeInfo : tmMcTimeInfoList) {
            returnCode = checkMcTimeWeekInfo(dayOfWeek, tmMcTimeInfo);
            if (returnCode != CommonConstant.PROCESS_SUCCESS) {
                /* 未匹配到满足条件的星期X,继续判断下一组时间规则 */
                rglog.info("未匹配到满足条件的星期X,继续判断下一组时间规则");
            } else {
                /* 匹配到满足条件的星期X,进一步判断时间范围是否满足条件 */
                int retCode = checkMcTimeRangeInfo(transTime, tmMcTimeInfo);
                if (CommonConstant.PROCESS_SUCCESS == retCode) {
                    /* 时间规则匹配成功 */
                    matchFlag = CommonConstant.FLAG_SET;
                    break;
                } else {
                    /* 时间规则匹配失败,需要继续判断下一组时间规则 */
                    rglog.info("hhmms时间规则匹配失败,需要继续判断下一组时间规则");
                }
            }
        }

        /* 时间规则匹配成功即可,无需记录对应信息 */
        if (CommonConstant.FLAG_SET == matchFlag) {
            rglog.info("时间规则匹配成功");
            return CommonConstant.PROCESS_SUCCESS;
        } else {
            return CommonConstant.PROCESS_FAILED;
        }
    }

    /**
     * 判断营销活动时间规则是否支持
     * 支持返回0
     * 不支持返回-1
     *
     * @param dayOfWeek    日期标记
     * @param tmMcTimeInfo 营销活动时间信息表
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/14 15:25
     */
    private int checkMcTimeWeekInfo(int dayOfWeek, TMMcTimeInfo tmMcTimeInfo) {

        String weekString = tmMcTimeInfo.getFlagMonday() + tmMcTimeInfo.getFlagTuesday() + tmMcTimeInfo.getFlagWednesday()
                + tmMcTimeInfo.getFlagThursday() + tmMcTimeInfo.getFlagFriday() + tmMcTimeInfo.getFlagSaturday() + tmMcTimeInfo.getFlagSunday();

        if (CommonConstant.WEEK_FLAG_ALL_NOT_SET.equals(weekString) || CommonConstant.WEEK_FLAG_ALL_SET.equals(weekString)) {
            /* 不区分星期一至星期日 */
            return CommonConstant.PROCESS_SUCCESS;
        } else {
            /* 区分星期一至星期日 */
            switch (dayOfWeek) {
                case CommonConstant.WEEK_MONDAY:
                    if (CommonConstant.WEEK_FLAG_SET.equals(tmMcTimeInfo.getFlagMonday())) {
                        return CommonConstant.PROCESS_SUCCESS;
                    }
                    break;
                case CommonConstant.WEEK_TUESDAY:
                    if (CommonConstant.WEEK_FLAG_SET.equals(tmMcTimeInfo.getFlagTuesday())) {
                        return CommonConstant.PROCESS_SUCCESS;
                    }
                    break;
                case CommonConstant.WEEK_WEDNESDAY:
                    if (CommonConstant.WEEK_FLAG_SET.equals(tmMcTimeInfo.getFlagWednesday())) {
                        return CommonConstant.PROCESS_SUCCESS;
                    }
                    break;
                case CommonConstant.WEEK_THURSDAY:
                    if (CommonConstant.WEEK_FLAG_SET.equals(tmMcTimeInfo.getFlagThursday())) {
                        return CommonConstant.PROCESS_SUCCESS;
                    }
                    break;
                case CommonConstant.WEEK_FRIDAY:
                    if (CommonConstant.WEEK_FLAG_SET.equals(tmMcTimeInfo.getFlagFriday())) {
                        return CommonConstant.PROCESS_SUCCESS;
                    }
                    break;
                case CommonConstant.WEEK_SATURDAY:
                    if (CommonConstant.WEEK_FLAG_SET.equals(tmMcTimeInfo.getFlagSaturday())) {
                        return CommonConstant.PROCESS_SUCCESS;
                    }
                    break;
                case CommonConstant.WEEK_SUNDAY:
                    if (CommonConstant.WEEK_FLAG_SET.equals(tmMcTimeInfo.getFlagSunday())) {
                        return CommonConstant.PROCESS_SUCCESS;
                    }
                    break;
                default:
                    rglog.error("错误的日期,DAY_OF_WEEK=<{}>", dayOfWeek);
                    return CommonConstant.PROCESS_FAILED;
            }
            return CommonConstant.PROCESS_FAILED;
        }
    }

    /**
     * 判断营销活动时间范围是否支持
     * 在时间范围内返回0
     * 未在时间范围内返回-1
     *
     * @param transTime    当前交易时间
     * @param tmMcTimeInfo 营销活动时间信息表
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/14 15:26
     */
    private int checkMcTimeRangeInfo(String transTime, TMMcTimeInfo tmMcTimeInfo) {

        BigDecimal currentTime = new BigDecimal(transTime).setScale(CommonConstant.ZERO, RoundingMode.HALF_UP);
        BigDecimal startTime = new BigDecimal(tmMcTimeInfo.getStartTime().trim().concat("0000")).setScale(CommonConstant.ZERO, RoundingMode.HALF_UP);
        BigDecimal endTime = new BigDecimal(tmMcTimeInfo.getEndTime().trim().concat("0000")).setScale(CommonConstant.ZERO, RoundingMode.HALF_UP);

        if (CommonConstant.ZERO <= currentTime.compareTo(startTime) && CommonConstant.ZERO >= currentTime.compareTo(endTime)) {
            /* 当前交易时间在营销活动时间范围内,时间规则判断通过 */
            return CommonConstant.PROCESS_SUCCESS;
        } else {
            /* 当前交易时间未在营销活动时间范围内,时间规则判断不通过 */
            return CommonConstant.PROCESS_FAILED;
        }
    }

    /**
     * 判断当前交易用户是否在用户白名单中
     * 在白名单中返回0
     * 未在白名单中返回-1
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @param userId 用户ID
     * @return int
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/14 15:52
     */
    private List<TMMcUserInfo> checkUserInfo(String instId, String mcNo, String userId) throws Exception {

        //查询上送用户的卡bin信息
        BinInfoService binInfoService = new BinInfoServiceImpl();
        BinInfo binInfo = binInfoService.getCardBinInfo(userId);
        if (null != binInfo) {
            String binNo = binInfo.getBinNo();
            rglog.info("通过用户号<{}> 查询卡bin信息为 <{}>！", userId, binNo);
            userId = userId + "," + binNo;
        } else {
            rglog.info("通过用户号<{}> 查询卡bin信息为空！", userId);
        }

        McUserInfoMapper mcUserInfoMapper = new McUserInfoMapperImpl();

        return mcUserInfoMapper.selectMcUserInfoListByInstIdMcNoAcctNo(instId, mcNo, userId);
    }

    /**
     * 查询减免类营销活动规则信息
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param parameter 参数
     * @param mcType    营销活动类型
     * @return java.io.Serializable 营销活动规则信息实体类
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/18 20:06
     */
    private <T> Serializable getMatchedMcRuleInfo(String instId, String mcNo, String parameter, String mcType) throws Exception {

        McRuleInfoMapper mcRuleInfoMapper = new McRuleInfoMapperImpl();

        if (!StringUtil.isNullorEmpty(mcType)) {
            switch (McTypeEnum.getByValue(mcType)) {
                case REDUCTION_FIXED_AMOUNT:
                case REDUCTION_RANDOM_AMOUNT:
                case REDUCTION_FIXED_RATE:
                case REDUCTION_RANDOM_RATE:
                    return mcRuleInfoMapper.selectMoneyOffRuleInfoListOrderByCriteria(instId, mcNo, parameter);
                case COUPON_ALL:
                case COUPON_FREE:
                case COUPON_PAID:
                    return mcRuleInfoMapper.selectCouponRuleInfoByPrimaryKey(instId, mcNo, parameter);
                default:
                    return null;
            }
        } else {
            rglog.error("法人机构<{}>的营销活动编号<{}>的营销活动类型<{}>为空!", instId, mcNo, mcType);
            return null;
        }
    }

    /**
     * 查询减免类营销活动规则信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMoneyOffRuleInfo 减免类营销活动规则表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/2 22:27
     */
    private List<TMMcMoneyOffRuleInfo> selectMoneyOffRuleInfoList(String instId, String mcNo) throws Exception {

        McRuleInfoMapper mcRuleInfoMapper = new McRuleInfoMapperImpl();
        return mcRuleInfoMapper.selectMoneyOffRuleInfoList(instId, mcNo);
    }

    /**
     * 根据营销活动种类和规则计算补贴减免金额
     *
     * @param txnData  (合并)支付使用XX类营销活动交易信息
     * @param mcType   营销活动类型
     * @param ruleInfo XX类营销活动规则实体类
     * @return java.lang.String 总补贴资金
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/18 19:55
     */
    private String calculateMcDiscountAmount(Object txnData, String mcType, Object ruleInfo) throws Exception {

        if (!StringUtil.isNullorEmpty(mcType)) {
            switch (McTypeEnum.getByValue(mcType)) {
                case REDUCTION_FIXED_AMOUNT:
                    /* 满额立减固定金额 */
                    return calculateReductionFixedAmount((McMoneyOffTxnData) txnData, (TMMcMoneyOffRuleInfo) ruleInfo);
                case REDUCTION_RANDOM_AMOUNT:
                    /* 满额立减随机金额 */
                    return calculateReductionRandomAmount((McMoneyOffTxnData) txnData, (TMMcMoneyOffRuleInfo) ruleInfo);
                case REDUCTION_FIXED_RATE:
                    /* 满额固定折扣 */
                    return calculateReductionFixedRate((McMoneyOffTxnData) txnData, (TMMcMoneyOffRuleInfo) ruleInfo);
                case REDUCTION_RANDOM_RATE:
                    /* 满额随机折扣 */
                    return calculateReductionRandomRate((McMoneyOffTxnData) txnData, (TMMcMoneyOffRuleInfo) ruleInfo);
                case COUPON_ALL:
                case COUPON_FREE:
                case COUPON_PAID:
                    /* 卡券类的不需要计算,直接使用卡券面额 */
                    return ((McCouponTxnData) txnData).getCouponAmt();
                case MCHNT_FEE_DISCOUNT:
                    return calculateMchntFeeDiscountSubsidy((McMchntFeeDiscountTxnData) txnData);
                default:
                    /* 其他类型营销活动 */
                    return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 计算满额立减固定金额类活动减免金额
     * 满减如果减不到指定金额则不进行优惠
     *
     * @param mcMoneyOffTxnData    (合并)支付使用减免类交易信息
     * @param tmMcMoneyOffRuleInfo 减免类营销活动规则表
     * @return java.lang.String 补贴金额
     * @author Jinan Liu
     * @since 2020/4/14 17:54
     */
    private String calculateReductionFixedAmount(McMoneyOffTxnData mcMoneyOffTxnData, TMMcMoneyOffRuleInfo tmMcMoneyOffRuleInfo) {

        BigDecimal totalSubsidy = new BigDecimal(tmMcMoneyOffRuleInfo.getDiscountCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal orderAmt = new BigDecimal(mcMoneyOffTxnData.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        rglog.debug("TOTAL_SUBSIDY=<{}>, ORDER_AMT=<{}>", totalSubsidy.toString(), orderAmt.toString());

        mcMoneyOffTxnData.setFloorAmt(totalSubsidy.toString());
        mcMoneyOffTxnData.setCellingAmt(totalSubsidy.toString());

        if (CommonConstant.ZERO < totalSubsidy.compareTo(orderAmt)) {
            /* 优惠金额大于等于订单金额,减不到指定金额则不进行优惠 */
            totalSubsidy = orderAmt;
        }

        rglog.info("优惠金额TOTAL_SUBSIDY=<{}>, 订单金额ORDER_AMT=<{}>", totalSubsidy.toString(), orderAmt.toString());

        return totalSubsidy.toString();
    }

    /**
     * 计算满额立减随机金额减免金额
     *
     * @param mcMoneyOffTxnData    (合并)支付使用减免类交易信息
     * @param tmMcMoneyOffRuleInfo 减免类营销活动规则表
     * @return java.lang.String 补贴金额
     * @author Jinan Liu
     * @since 2020/4/14 17:54
     */
    private String calculateReductionRandomAmount(McMoneyOffTxnData mcMoneyOffTxnData, TMMcMoneyOffRuleInfo tmMcMoneyOffRuleInfo) {

        BigDecimal orderAmt = new BigDecimal(mcMoneyOffTxnData.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal minValue = new BigDecimal(tmMcMoneyOffRuleInfo.getDiscountFloor()).setScale(CommonConstant.DECIMAL_SCALE_FIVE, RoundingMode.HALF_UP);
        BigDecimal maxValue = new BigDecimal(tmMcMoneyOffRuleInfo.getDiscountCelling()).setScale(CommonConstant.DECIMAL_SCALE_FIVE, RoundingMode.HALF_UP);

        mcMoneyOffTxnData.setFloorAmt(minValue.toString());
        mcMoneyOffTxnData.setCellingAmt(maxValue.toString());

        BigDecimal totalSubsidy = getRandomBetweenMinAndMax(minValue, maxValue);
        rglog.info("最初随机值为 ：TOTAL_SUBSIDY=<{}>", totalSubsidy.toString());

        if (CommonConstant.ZERO < totalSubsidy.compareTo(orderAmt)) {
            /* 优惠金额大于等于订单金额,优惠金额=订单金额 */
            totalSubsidy = orderAmt;
        }

        rglog.info("优惠金额TOTAL_SUBSIDY=<{}>, 订单金额ORDER_AMT=<{}>", totalSubsidy.toString(), orderAmt.toString());

        return totalSubsidy.toString();
    }

    /**
     * 计算满额固定折扣减免金额
     *
     * @param mcMoneyOffTxnData    (合并)支付使用减免类交易信息
     * @param tmMcMoneyOffRuleInfo 减免类营销活动规则表
     * @return java.lang.String 补贴金额
     * @author Jinan Liu
     * @since 2020/4/14 17:54
     */
    private String calculateReductionFixedRate(McMoneyOffTxnData mcMoneyOffTxnData, TMMcMoneyOffRuleInfo tmMcMoneyOffRuleInfo) {

        BigDecimal orderAmt = new BigDecimal(mcMoneyOffTxnData.getOrderAmt());
        BigDecimal discountRate = BigDecimal.TEN.subtract(new BigDecimal(tmMcMoneyOffRuleInfo.getDiscountCelling())).divide(BigDecimal.TEN);
        BigDecimal discountLimit = new BigDecimal(tmMcMoneyOffRuleInfo.getDiscountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        BigDecimal totalSubsidy = orderAmt.multiply(discountRate).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        mcMoneyOffTxnData.setFloorAmt(totalSubsidy.toString());
        mcMoneyOffTxnData.setCellingAmt(totalSubsidy.toString());

        rglog.info("TOTAL_SUBSIDY=<{}>, DISCOUNT_LIMIT=<{}>", totalSubsidy.toString(), discountLimit.toString());

        if (CommonConstant.ZERO <= totalSubsidy.compareTo(discountLimit)) {
            /* 优惠金额大于等于优惠上限,优惠金额=优惠上限 */
            totalSubsidy = discountLimit;
        }

        rglog.info("TOTAL_SUBSIDY=<{}>, DISCOUNT_LIMIT=<{}>", totalSubsidy.toString(), discountLimit.toString());

        return totalSubsidy.toString();
    }

    /**
     * 计算满额随机折扣减免金额
     *
     * @param mcMoneyOffTxnData    (合并)支付使用减免类交易信息
     * @param tmMcMoneyOffRuleInfo 减免类营销活动规则表
     * @return java.lang.String 补贴金额
     * @author Jinan Liu
     * @since 2020/4/14 17:54
     */
    private String calculateReductionRandomRate(McMoneyOffTxnData mcMoneyOffTxnData, TMMcMoneyOffRuleInfo tmMcMoneyOffRuleInfo) {

        BigDecimal orderAmt = new BigDecimal(mcMoneyOffTxnData.getOrderAmt());
        BigDecimal minDiscountRate = BigDecimal.TEN.subtract(new BigDecimal(tmMcMoneyOffRuleInfo.getDiscountFloor())).divide(BigDecimal.TEN);
        BigDecimal maxDiscountRate = BigDecimal.TEN.subtract(new BigDecimal(tmMcMoneyOffRuleInfo.getDiscountCelling())).divide(BigDecimal.TEN);
        BigDecimal discountLimit = new BigDecimal(tmMcMoneyOffRuleInfo.getDiscountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        BigDecimal minTotalSubsidy = orderAmt.multiply(minDiscountRate).setScale(CommonConstant.DECIMAL_SCALE_FIVE, RoundingMode.HALF_UP);
        BigDecimal maxTotalSubsidy = orderAmt.multiply(maxDiscountRate).setScale(CommonConstant.DECIMAL_SCALE_FIVE, RoundingMode.HALF_UP);

        BigDecimal totalSubsidy = getRandomBetweenMinAndMax(minTotalSubsidy, maxTotalSubsidy);

        mcMoneyOffTxnData.setFloorAmt(minTotalSubsidy.toString());
        mcMoneyOffTxnData.setCellingAmt(maxTotalSubsidy.toString());

        rglog.info("TOTAL_SUBSIDY=<{}>, DISCOUNT_LIMIT=<{}>", totalSubsidy.toString(), discountLimit.toString());

        if (CommonConstant.ZERO <= totalSubsidy.compareTo(discountLimit)) {
            /* 优惠金额大于等于优惠上限,优惠金额=优惠上限 */
            totalSubsidy = discountLimit;
        }

        rglog.info("TOTAL_SUBSIDY=<{}>, DISCOUNT_LIMIT=<{}>", totalSubsidy.toString(), discountLimit.toString());

        return totalSubsidy.toString();
    }


    /**
     * 生成范围内随机数
     *
     * @param minValue 最小值
     * @param maxValue 最大值
     * @return java.math.BigDecimal 生成的随机数
     * @author liujinan
     * @since 2020/8/26 20:45
     */
    private BigDecimal getRandomBetweenMinAndMax(BigDecimal minValue, BigDecimal maxValue) {
        /* 生成随机数 范围为 [0,1) */
        Double randoms = new SecureRandom().nextDouble();
        BigDecimal random = BigDecimal.valueOf(randoms);
        rglog.info("生成的随机盐值:<{}>", random.toString());
        BigDecimal discount = random.multiply(maxValue.subtract(minValue)).add(minValue).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        if (CommonConstant.ZERO == discount.compareTo(maxValue)) {
            return discount.subtract(BigDecimal.ONE.divide(BigDecimal.TEN).divide(BigDecimal.TEN)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        } else {
            return discount;
        }
    }


    /**
     * 计算银行和商户营销资金出资金额
     *
     * @param mcSubsidyData 营销活动补贴数据对象
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/18 21:58
     */
    private int calculateBankAndMchntSubsidyRatio(McSubsidyData mcSubsidyData) {

        switch (McTypeEnum.getByValue(mcSubsidyData.getMcType())) {
            case REDUCTION_FIXED_AMOUNT:
            case REDUCTION_RANDOM_AMOUNT:
            case REDUCTION_FIXED_RATE:
            case REDUCTION_RANDOM_RATE:
            case COUPON_ALL:
            case COUPON_FREE:
            case COUPON_PAID:
                switch (mcSubsidyData.getSponsor()) {
                    case CommonConstant.SPONSOR_BANK:
                        /* 银行全资 */
                        mcSubsidyData.setBankSubsidy(mcSubsidyData.getTotalSubsidy());
                        mcSubsidyData.setMchntSubsidy(BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
                        return CommonConstant.PROCESS_SUCCESS;
                    case CommonConstant.SPONSOR_MIXED:
                        /* 银行、商户合资 */
                        String bankRatio = mcSubsidyData.getBankBudgetRatio();
                        BigDecimal totalAmt = new BigDecimal(mcSubsidyData.getTotalSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        BigDecimal bankAmt = new BigDecimal(bankRatio).multiply(totalAmt).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        BigDecimal mchntAmt = totalAmt.subtract(bankAmt).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                        mcSubsidyData.setBankSubsidy(bankAmt.toString());
                        mcSubsidyData.setMchntSubsidy(mchntAmt.toString());

                        /* 预算 */
                        BigDecimal budget = new BigDecimal(mcSubsidyData.getBudget()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        /* 银行出资预算 */
                        BigDecimal bankBudget = new BigDecimal(mcSubsidyData.getBankBudget()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        /* 预期参与商户数量 */
                        BigDecimal expectMchntQty = new BigDecimal(mcSubsidyData.getExpectMchntQty()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
                        if (CommonConstant.IS_EQUAL_TO == BigDecimal.ZERO.compareTo(expectMchntQty)) {
                            return CommonConstant.PROCESS_FAILED;
                        }

                        /* 计算商户累计优惠额度上限 */
                        mcSubsidyData.setBankDiscountLimitAmt(bankBudget.divide(expectMchntQty, CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
                        mcSubsidyData.setMchntDiscountLimitAmt(budget.subtract(bankBudget).divide(expectMchntQty, CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());

                        rglog.debug("TOTAL_SUBSIDY=<{}>, BANK_SUBSIDY=<{}>, MCHNT_SUBSIDY=<{}>", mcSubsidyData.getTotalSubsidy(), mcSubsidyData.getBankSubsidy(), mcSubsidyData.getMchntSubsidy());

                        return CommonConstant.PROCESS_SUCCESS;
                    case CommonConstant.SPONSOR_MCHNT:
                    case CommonConstant.SPONSOR_MCHNT_NORECHARGE:
                        /* 商户全资 */
                        mcSubsidyData.setBankSubsidy(BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
                        mcSubsidyData.setMchntSubsidy(mcSubsidyData.getTotalSubsidy());
                        return CommonConstant.PROCESS_SUCCESS;
                    default:
                        rglog.error("错误的营销活动出资方式, SPONSOR=<{}>", mcSubsidyData.getSponsor());
                        return CommonConstant.PROCESS_FAILED;
                }
            default:
                rglog.error("营销活动类型<{}>异常,不可计算银行与商户出资比例!", mcSubsidyData.getMcType());
                return CommonConstant.PROCESS_FAILED;
        }
    }

    /**
     * 获取所有额度和限额控制
     *
     * @param object (合并)支付使用XX类营销活动交易信息
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/18 21:57
     */
    private int fetchAllQuotaData(Object object) throws Exception {

        rglog.debug("类名是<{}>", object.getClass().toString());

        if (object instanceof MoneyOffAmountData) {
            /* 减免类营销活动各维度统计数据获取 */
            rglog.info("开始处理减免类营销活动统计数据获取流程!");
            return fetchAllToClientMcQuotaData(object);

        } else if (object instanceof McCouponTxnData) {
            /* 卡券类营销活动各维度统计数据获取 */
            rglog.info("开始处理卡券类营销活动统计数据获取流程!");
            return fetchAllToClientMcQuotaData(object);

        } else if (object instanceof McMchntFeeDiscountTxnData) {
            /* 商户手续费优惠类营销活动各维度统计数据获取 */
            rglog.info("开始处理商户手续费优惠类营销活动统计数据获取流程!");
            return fetchAllMchntFeeDiscountMcQuotaData(object);

        } else {
            rglog.error("错误的对象类型<{}>", object.getClass());
            return CommonConstant.PROCESS_FAILED;
        }
    }

    /**
     * 检查所有额度和限额控制
     *
     * @param mcInfo  XX类营销活动信息表
     * @param txnData (合并)支付使用XX类交易信息
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/18 22:09
     */
    private int checkAllQuotaWithMcType(Object mcInfo, Object txnData) throws Exception {

        rglog.debug("检查所有额度和限额控制流程开始!");

        String mcType;

        if (mcInfo instanceof TMMcMoneyOffInfo) {
            mcType = ((TMMcMoneyOffInfo) mcInfo).getMcType();

            if (!StringUtil.isNullorEmpty(mcType)) {
                switch (McTypeEnum.getByValue(mcType)) {
                    case REDUCTION_FIXED_AMOUNT:
                        /* 满额立减固定金额 */
                        return checkReductionFixedAmountLimits((TMMcMoneyOffInfo) mcInfo, (MoneyOffAmountData) txnData);
                    case REDUCTION_RANDOM_AMOUNT:
                        /* 满额立减随机金额 */
                    case REDUCTION_FIXED_RATE:
                        /* 满额固定折扣 */
                    case REDUCTION_RANDOM_RATE:
                        /* 满额随机折扣 */
                        return checkReductionRandomRateLimits((TMMcMoneyOffInfo) mcInfo, (MoneyOffAmountData) txnData);
                    default:
                        /* 其他类型营销活动 */
                        return CommonConstant.PROCESS_FAILED;
                }
            } else {
                return CommonConstant.PROCESS_FAILED;
            }
        } else if (txnData instanceof McCouponTxnData) {
            /* 卡券类优惠信息判断 */
            return checkCouponLimits((McCouponTxnData) txnData);

        } else if (txnData instanceof McMchntFeeDiscountTxnData) {
            /* 商户手续费优惠信息判断 */
            return checkMchntFeeDiscountLimits((McMchntFeeDiscountTxnData) txnData);

        } else {
            /* 其他类型营销活动 */
            return CommonConstant.PROCESS_FAILED;
        }
    }


    /**
     * 查询对客户营销活动统计表数据
     *
     * @param instId    法人机构号
     * @param mcNo      商户编号
     * @param ruleIndex 规则顺序号
     * @return cc.rengu.igas.momp.common.entity.TMStat2C 对客户营销活动统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/14 22:47
     */
    private TMStat2C selectToClientMcLevelStatistics(String instId, String mcNo, String ruleIndex) throws Exception {

        TMStat2C tmStat2C = new TMStat2C();
        tmStat2C.setInstId(instId);
        tmStat2C.setMcNo(mcNo);
        tmStat2C.setRuleIndex(ruleIndex);

        TMStat2CMapper tmStat2CMapper = new TMStat2CMapperImpl();
        return tmStat2CMapper.selectToClientMcLevelStatistics(tmStat2C);
    }

    /**
     * 查询对客户营销活动单日统计表数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param txnDate   交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStat2CDay 对客户营销活动单日统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/14 22:52
     */
    private TMStat2CDay selectToClientMcDayStatistics(String instId, String mcNo, String ruleIndex, String txnDate) throws Exception {

        TMStat2CDay tmStat2CDay = new TMStat2CDay();
        tmStat2CDay.setInstId(instId);
        tmStat2CDay.setMcNo(mcNo);
        tmStat2CDay.setRuleIndex(ruleIndex);
        tmStat2CDay.setTxnDate(txnDate);

        TMStat2CDayMapper tmStat2CDayMapper = new TMStat2CDayMapperImpl();
        return tmStat2CDayMapper.selectToClientMcDayStatistics(tmStat2CDay);
    }

    /**
     * 查询对客户营销活动商户统计表数据
     *
     * @param instId  法人机构号
     * @param mcNo    营销活动编号
     * @param mchntNo 商户编号
     * @return cc.rengu.igas.momp.common.entity.TMStat2CMchnt 对客户营销活动商户统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/15 15:38
     */
    private TMStat2CMchnt selectToClientMcMchntStatistics(String instId, String mcNo, String mchntNo) throws Exception {

        TMStat2CMchnt tmStat2CMchnt = new TMStat2CMchnt();
        tmStat2CMchnt.setInstId(instId);
        tmStat2CMchnt.setMcNo(mcNo);
        tmStat2CMchnt.setMchntNo(mchntNo);

        TMStat2CMchntMapper tmStat2CMchntMapper = new TMStat2CMchntMapperImpl();
        return tmStat2CMchntMapper.selectToClientMcMchntStatistics(tmStat2CMchnt);
    }

    /**
     * 查询对客户营销活动商户单日统计表数据
     *
     * @param instId  法人机构号
     * @param mcNo    营销活动编号
     * @param mchntNo 商户编号
     * @param txnDate 交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStat2CMchntDay
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/15 17:11
     */
    private TMStat2CMchntDay selectToClientMcMchntDayStatistics(String instId, String mcNo, String mchntNo, String txnDate) throws Exception {

        TMStat2CMchntDay tmStat2CMchntDay = new TMStat2CMchntDay();
        tmStat2CMchntDay.setInstId(instId);
        tmStat2CMchntDay.setMcNo(mcNo);
        tmStat2CMchntDay.setMchntNo(mchntNo);
        tmStat2CMchntDay.setTxnDate(txnDate);

        TMStat2CMchntDayMapper tmStat2CMchntDayMapper = new TMStat2CMchntDayMapperImpl();
        return tmStat2CMchntDayMapper.selectToClientMcMchntDayStatistics(tmStat2CMchntDay);
    }


    /**
     * 使用主键取手续费减免活动统计表单条数据
     *
     * @param instId    法人机构编号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @return cc.rengu.igas.momp.common.entity.TMStatMfd 手续费减免活动统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 22:42
     */
    private TMStatMfd selectMchntFeeDiscountStatisticsByPK(String instId, String mcNo, String ruleIndex) throws Exception {

        TMStatMfdMapper tmStatMfdMapper = new TMStatMfdMapperImpl();
        return tmStatMfdMapper.selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
    }

    /**
     * 使用主键查询手续费减免活动周期统计表单条数据
     *
     * @param instId          法人机构号
     * @param mcNo            营销活动编号
     * @param ruleIndex       规则顺序号
     * @param periodStartDate 周期起始日期
     * @param periodEndDate   周期结束日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod 手续费减免活动周期统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 23:38
     */
    private TMStatMfdPeriod selectMchntFeeDiscountPeriodStatisticsByPK(String instId, String mcNo, String ruleIndex, String periodStartDate, String periodEndDate) throws Exception {

        TMStatMfdPeriodMapper tmStatMfdPeriodMapper = new TMStatMfdPeriodMapperImpl();
        return tmStatMfdPeriodMapper.selectMchntFeeDiscountPeriodStatisticsByPK(instId, mcNo, ruleIndex, periodStartDate, periodEndDate);
    }

    /**
     * 使用主键取手续费减免活动单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param transDate 交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdDay 手续费减免活动单日统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 23:23
     */
    private TMStatMfdDay selectMchntFeeDiscountDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String transDate) throws Exception {

        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        return tmStatMfdDayMapper.selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, transDate);
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId          法人机构号
     * @param mcNo            营销活动编号
     * @param ruleIndex       规则顺序号
     * @param mchntNo         商户编号
     * @param periodStartDate 统计周期起始日期
     * @param periodEndDate   统计周期结束日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt 手续费减免活动商户统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 23:40
     */
    private TMStatMfdMchnt selectMchntFeeDiscountMchntStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String periodStartDate, String periodEndDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
    }

    /**
     * 使用主键取手续费减免活动商户单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param mchntNo   商户编号
     * @param txnDate   交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchntDay 手续费减免活动商户单日统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 23:42
     */
    private TMStatMfdMchntDay selectMchntFeeDiscountMchntDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        return tmStatMfdMchntDayMapper.selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 减免类规则信息赋值
     *
     * @param tmMcMoneyOffRuleInfo 减免类营销活动规则表
     * @param moneyOffAmountData   减免类营销活动金额数据
     * @author Jinan Liu
     * @since 2020/4/15 13:52
     */
    private void copyMoneyOffRuleInfoAmountData(TMMcMoneyOffRuleInfo tmMcMoneyOffRuleInfo, MoneyOffAmountData moneyOffAmountData) {

        /* 规则信息-顺序号 */
        moneyOffAmountData.setRuleIndex(tmMcMoneyOffRuleInfo.getRuleIndex());
        /* 规则信息-活动门槛 */
        moneyOffAmountData.setCriteria(tmMcMoneyOffRuleInfo.getCriteria());
        /* 规则信息-优惠力度下限 */
        moneyOffAmountData.setDiscountFloor(tmMcMoneyOffRuleInfo.getDiscountFloor());
        /* 规则信息-优惠力度上限 */
        moneyOffAmountData.setDiscountCelling(tmMcMoneyOffRuleInfo.getDiscountCelling());
        /* 规则信息-总优惠数量 */
        moneyOffAmountData.setDiscountQuantity(tmMcMoneyOffRuleInfo.getDiscountQuantity());
        /* 规则信息-单次优惠限制 */
        moneyOffAmountData.setDiscountLimit(tmMcMoneyOffRuleInfo.getDiscountLimit());
        /* 规则信息-优惠总预算 */
        moneyOffAmountData.setRuleBudget(tmMcMoneyOffRuleInfo.getBudget());
        /* 规则信息-单日消耗预算 */
        moneyOffAmountData.setBudgetDayLimit(tmMcMoneyOffRuleInfo.getBudgetDayLimit());
    }

    /**
     * 对客类营销活动统计数据赋值
     *
     * @param tmStat2C 对客户营销活动统计表
     * @param object   操作对象
     * @author Jinan Liu
     * @since 2020/4/18 21:54
     */
    private void copyMoneyOffToClientStatData(TMStat2C tmStat2C, Object object) {

        if (object instanceof MoneyOffAmountData) {
            /* 营销活动累计-总预算累计消耗笔数 */
            ((MoneyOffAmountData) object).setMcTotalQtyAcc(tmStat2C.getTotalQtyAcc());
            /* 营销活动累计-总预算累计消耗金额 */
            ((MoneyOffAmountData) object).setMcTotalAmtAcc(tmStat2C.getTotalAmtAcc());
        } else {
            /* 营销活动累计-总预算累计消耗笔数 */
            ((McCouponTxnData) object).setMcTotalQtyAcc(tmStat2C.getTotalQtyAcc());
            /* 营销活动累计-总预算累计消耗金额 */
            ((McCouponTxnData) object).setMcTotalAmtAcc(tmStat2C.getTotalAmtAcc());
        }
    }

    /**
     * 对客类营销活动单日统计数据赋值
     *
     * @param tmStat2CDay 对客户营销活动单日统计表
     * @param object      操作对象
     * @author Jinan Liu
     * @since 2020/4/18 21:54
     */
    private void copyMoneyOffToClientSingleDayStatData(TMStat2CDay tmStat2CDay, Object object) {

        if (object instanceof MoneyOffAmountData) {
            /* 营销活动单日累计-总预算累计消耗笔数 */
            ((MoneyOffAmountData) object).setDayTotalQtyAcc(tmStat2CDay.getTotalQtyAcc());
            /* 营销活动单日累计-总预算累计消耗金额 */
            ((MoneyOffAmountData) object).setDayTotalAmtAcc(tmStat2CDay.getTotalAmtAcc());
        } else {
            /* 营销活动单日累计-总预算累计消耗笔数 */
            ((McCouponTxnData) object).setDayTotalQtyAcc(tmStat2CDay.getTotalQtyAcc());
            /* 营销活动单日累计-总预算累计消耗金额 */
            ((McCouponTxnData) object).setDayTotalAmtAcc(tmStat2CDay.getTotalAmtAcc());
        }
    }

    /**
     * 对客户营销活动商户统计数据赋值
     *
     * @param tmStat2CMchnt 对客户营销活动商户统计表
     * @param object        操作对象
     * @author Jinan Liu
     * @since 2020/4/18 21:55
     */
    private void copyMoneyOffToClientMchntStatData(TMStat2CMchnt tmStat2CMchnt, Object object) {

        if (object instanceof MoneyOffAmountData) {
            /* 营销活动单日累计-总预算累计消耗笔数 */
            ((MoneyOffAmountData) object).setMchntTotalQtyAcc(tmStat2CMchnt.getTotalQtyAcc());
            /* 营销活动单日累计-总预算累计消耗金额 */
            ((MoneyOffAmountData) object).setMchntTotalAmtAcc(tmStat2CMchnt.getTotalAmtAcc());
        } else {
            /* 营销活动单日累计-总预算累计消耗笔数 */
            ((McCouponTxnData) object).setMchntTotalQtyAcc(tmStat2CMchnt.getTotalQtyAcc());
            /* 营销活动单日累计-总预算累计消耗金额 */
            ((McCouponTxnData) object).setMchntTotalAmtAcc(tmStat2CMchnt.getTotalAmtAcc());
        }
    }

    /**
     * 对客户营销活动商户单日统计数据赋值
     *
     * @param tmStat2CMchntDay 对客户营销活动商户单日统计表
     * @param object           操作对象
     * @author Jinan Liu
     * @since 2020/4/18 21:54
     */
    private void copyMoneyOffToClientMchntDayStatData(TMStat2CMchntDay tmStat2CMchntDay, Object object) {

        if (object instanceof MoneyOffAmountData) {
            /* 营销活动单日累计-累计优惠笔数 */
            ((MoneyOffAmountData) object).setMchntDayTotalQtyAcc(tmStat2CMchntDay.getTotalQtyAcc());
            /* 营销活动单日累计-累计优惠金额 */
            ((MoneyOffAmountData) object).setMchntDayTotalAmtAcc(tmStat2CMchntDay.getTotalAmtAcc());
        } else {
            /* 营销活动单日累计-累计优惠笔数 */
            ((McCouponTxnData) object).setMchntDayTotalQtyAcc(tmStat2CMchntDay.getTotalQtyAcc());
            /* 营销活动单日累计-累计优惠金额 */
            ((McCouponTxnData) object).setMchntDayTotalAmtAcc(tmStat2CMchntDay.getTotalAmtAcc());
        }
    }

    /**
     * 满额立减固定金额类减免营销活动交易限额处理
     *
     * @param tmMcMoneyOffInfo   减免类营销活动信息表
     * @param moneyOffAmountData 减免类营销活动金额数据
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/15 14:27
     */
    private int checkReductionFixedAmountLimits(TMMcMoneyOffInfo tmMcMoneyOffInfo, MoneyOffAmountData moneyOffAmountData) {

        /* 当前优惠金额 */
        BigDecimal totalSubsidy = new BigDecimal(moneyOffAmountData.getTotalSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        rglog.debug("TOTAL_SUBSIDY=<{}>", totalSubsidy.toString());

        /* 规则信息-顺序号 */
        String ruleIndex = moneyOffAmountData.getRuleIndex();
        /* 规则信息-总优惠数量 */
        BigDecimal ruleDiscountQuantity = new BigDecimal(moneyOffAmountData.getDiscountQuantity()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
        /* 规则信息-单日消耗预算 */
        BigDecimal dayQtyLimit = new BigDecimal(moneyOffAmountData.getBudgetDayLimit()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
        rglog.debug("RULE_INDEX=<{}>, RULE_DISCOUNT_QUANTITY=<{}>, DAY_QUANTITY_LIMIT=<{}>", ruleIndex, ruleDiscountQuantity.toString(), dayQtyLimit.toString());

        /* 当前累计历史优惠笔数 */
        BigDecimal mcTotalDiscountQty = new BigDecimal(moneyOffAmountData.getMcTotalQtyAcc());
        /* 当前当日累计优惠笔数 */
        BigDecimal dayTotalDiscountQty = new BigDecimal(moneyOffAmountData.getDayTotalQtyAcc());
        /* 当前总累计优惠笔数 */
        BigDecimal totalDiscountQty = mcTotalDiscountQty.add(dayTotalDiscountQty).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
        rglog.debug("MC_TOTAL_DISCOUNT_QUANTITY=<{}>, DAY_TOTAL_DISCOUNT_QUANTITY=<{}>, TOTAL_DISCOUNT_QUANTITY=<{}>", mcTotalDiscountQty.toString(), dayTotalDiscountQty.toString(), totalDiscountQty.toString());

        /* 检查指定规则层面优惠笔数是否超出 */
        if (CommonConstant.ZERO < totalDiscountQty.add(BigDecimal.ONE).compareTo(ruleDiscountQuantity)) {
            rglog.info("当前累计优惠笔数<{}>已超出对应规则<{}>最大优惠笔数<{}>,不予优惠!", totalDiscountQty.toString(), ruleIndex, ruleDiscountQuantity.toString());
            return CommonConstant.PROCESS_FAILED;
        }

        /* 检查指定规则层面单日优惠笔数是否超出 */
        if (CommonConstant.ZERO < dayTotalDiscountQty.add(BigDecimal.ONE).compareTo(dayQtyLimit)) {
            rglog.info("当前单日累计优惠笔数<{}>已超出对应规则<{}>最大单日优惠笔数<{}>,不予优惠!", dayTotalDiscountQty.toString(), ruleIndex, dayQtyLimit.toString());
            return CommonConstant.PROCESS_FAILED;
        }

        /* 如果是银商联合的活动  检查指定规则层面单日优惠笔数是否超出 */
        if (CommonConstant.SPONSOR_MIXED.equals(tmMcMoneyOffInfo.getSponsor())) {
            BigDecimal mchntSubsidy = new BigDecimal(moneyOffAmountData.getMchntSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 每商户最大优惠金额 */
            BigDecimal mchntDiscountLimitAmt = new BigDecimal(moneyOffAmountData.getMchntDiscountLimitAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 商户历史累计优惠金额 */
            BigDecimal mchntTotalAmtAcc = new BigDecimal(moneyOffAmountData.getMchntTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 商户当日累计优惠金额 */
            BigDecimal mchntDayTotalAmtAcc = new BigDecimal(moneyOffAmountData.getMchntDayTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 商户截止到当前交易前累计优惠金额 */
            BigDecimal mchntCurrentTotalAmtAcc = mchntTotalAmtAcc.add(mchntDayTotalAmtAcc).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            /* 联合营销判断商户剩余可优惠额度 */
            if (CommonConstant.ZERO < mchntCurrentTotalAmtAcc.compareTo(mchntDiscountLimitAmt)) {
                /* 若当前商户累计交易金额大于商户最大优惠金额,流程结束,不予优惠 */
                rglog.info("当前商户累计优惠金额<{}>已超过商户最大优惠金额<{}>,不予优惠!", mchntCurrentTotalAmtAcc.toString(), mchntDiscountLimitAmt.toString());
                return CommonConstant.PROCESS_FAILED;
            } else {
                /* 若当前商户累计交易金额不大于商户最大优惠金额,但当前商户累计交易金额加本笔交易计算的优惠额大于商户最大优惠金额,则不予优惠 */
                if (CommonConstant.ZERO < mchntCurrentTotalAmtAcc.add(mchntSubsidy).compareTo(mchntDiscountLimitAmt)) {
                    rglog.info("当前商户累计优惠金额<{}>已超过商户最大优惠金额<{}>,不予优惠!", mchntCurrentTotalAmtAcc.add(mchntSubsidy).toString(), mchntDiscountLimitAmt.toString());
                    return CommonConstant.PROCESS_FAILED;
                }
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 满额满额立减随机金额类\满额固定折扣类\满额随机折扣类减免营销活动交易限额处理
     *
     * @param tmMcMoneyOffInfo   减免类营销活动信息表
     * @param moneyOffAmountData 减免类营销活动金额数据
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/15 17:43
     */
    private int checkReductionRandomRateLimits(TMMcMoneyOffInfo tmMcMoneyOffInfo, MoneyOffAmountData moneyOffAmountData) {

        /* 当前优惠金额 */
        BigDecimal totalSubsidy = new BigDecimal(moneyOffAmountData.getTotalSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        /* 规则信息-顺序号 */
        String ruleIndex = moneyOffAmountData.getRuleIndex();
        /* 规则信息-单次优惠限制 */
        BigDecimal discountLimit = new BigDecimal(moneyOffAmountData.getDiscountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        /* 规则信息-优惠总预算 */
        BigDecimal budget = new BigDecimal(moneyOffAmountData.getRuleBudget()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        /* 规则信息-单日消耗预算 */
        BigDecimal dayQtyLimit = new BigDecimal(moneyOffAmountData.getBudgetDayLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);


        /* 判断营销活动类型 */
        if (CommonConstant.ZERO != discountLimit.compareTo(BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP))) {
            /* 满额固定折扣或满额随机折扣,需要检查单次优惠限额 */
            if (CommonConstant.ZERO < totalSubsidy.compareTo(discountLimit)) {
                /* 减免金额已超过减免规则对应单次优惠上限,最高只可优惠单次优惠限额的金额 */
                rglog.error("减免金额<{}>超过减免规则对应单次优惠上限<{}>,最高只可优惠单次优惠限额的金额<{}>", totalSubsidy, discountLimit, discountLimit);
                totalSubsidy = discountLimit;
            }
            //判断优惠下限金额是否大于优惠金额
//            if (!StringUtil.isNullorEmpty(moneyOffAmountData.getFloorAmt())){
//                rglog.info("判断优惠下限金额是否大于优惠金额");
//                if (CommonConstant.ZERO > totalSubsidy.compareTo(new BigDecimal(moneyOffAmountData.getFloorAmt()))){
//                    rglog.error("优惠下限金额<{}>大于本次优惠金额<{}>，无优惠！",moneyOffAmountData.getFloorAmt(),totalSubsidy);
//                    return CommonConstant.PROCESS_FAILED;
//                }
//            }
        } else {
            /* 满额立减随机金额,无须检查单次优惠限制 */
            rglog.info("满额立减随机金额,无须检查单次优惠限制!");
        }


        /* 当前累计历史优惠金额-优惠前 */
        BigDecimal mcTotalDiscountAmt = new BigDecimal(moneyOffAmountData.getMcTotalAmtAcc());
        /* 当前当日累计优惠金额-优惠前 */
        BigDecimal dayTotalDiscountAmt = new BigDecimal(moneyOffAmountData.getDayTotalAmtAcc());
        /* 当前总累计优惠金额-优惠后 */
        BigDecimal totalDiscountAmt = totalSubsidy.add(mcTotalDiscountAmt).add(dayTotalDiscountAmt).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        /* 当前单日累计优惠金额-优惠后 */
        BigDecimal totalDayDiscountAmt = totalSubsidy.add(dayTotalDiscountAmt).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        /* 检查指定规则层面优惠金额是否超出 */
        if (CommonConstant.ZERO <= mcTotalDiscountAmt.add(dayTotalDiscountAmt).compareTo(budget)) {
            /* 当前累计历史优惠金额+当前当日累计优惠金额>=规则优惠额度,不可优惠 */
            rglog.info("当前优惠前累计优惠金额<{}>已超出对应规则<{}>最大优惠金额<{}>,不予优惠!", mcTotalDiscountAmt.add(dayTotalDiscountAmt).toString(), ruleIndex, budget.toString());
            return CommonConstant.PROCESS_FAILED;
        } else {
            if (CommonConstant.ZERO < totalDiscountAmt.compareTo(budget)) {
                /* 当前累计历史优惠金额+当前当日累计优惠金额+本次优惠金额>规则优惠额度,仅可优惠规则优惠额度-(当前累计历史优惠金额+当前当日累计优惠金额)部分金额 */
                totalSubsidy = budget.subtract(mcTotalDiscountAmt).subtract(dayTotalDiscountAmt).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                rglog.info("当前优惠后累计优惠金额<{}>已超出对应规则<{}>最大优惠金额<{}>,仅可优惠<{}>!", totalDiscountAmt.toString(), ruleIndex, budget.toString(), totalSubsidy);
                //判断优惠下限金额是否大于优惠金额
                if (!StringUtil.isNullorEmpty(moneyOffAmountData.getFloorAmt())) {
                    if (CommonConstant.ZERO > totalSubsidy.compareTo(new BigDecimal(moneyOffAmountData.getFloorAmt()))) {
                        rglog.info("优惠金额<{}>小于优惠下限金额<{}>,不予优惠", totalSubsidy, moneyOffAmountData.getFloorAmt());
                        return CommonConstant.PROCESS_FAILED;
                    }
                }
                if (tmMcMoneyOffInfo.getMcType().equals(McTypeEnum.REDUCTION_FIXED_RATE.getMcTypeCode())) {
                    rglog.info("活动类型为固定折扣，优惠金额<{}>小于固定折扣所优惠的金额,不予优惠", totalSubsidy);
                    return CommonConstant.PROCESS_FAILED;
                }
            } else {
                /* 当前累计历史优惠金额+当前当日累计优惠金额+本次优惠金额<=规则优惠额度,正常优惠 */
                rglog.debug("当前优惠后累计优惠金额<{}>未超出对应规则<{}>最大优惠金额<{}>,正常优惠!", totalDiscountAmt.toString(), ruleIndex, budget.toString());
            }
        }

        /* 检查指定规则层面单日优惠金额是否超出 */
        if (CommonConstant.ZERO <= dayTotalDiscountAmt.compareTo(dayQtyLimit)) {
            /* 当前累计单日优惠金额>=规则单日优惠额度,不可优惠 */
            rglog.info("当前优惠前单日累计优惠金额<{}>已超出对应规则<{}>最大单日优惠金额<{}>,不予优惠!", dayTotalDiscountAmt.toString(), ruleIndex, dayQtyLimit.toString());
            return CommonConstant.PROCESS_FAILED;
        } else {
            if (CommonConstant.ZERO < totalDayDiscountAmt.compareTo(dayQtyLimit)) {
                /* 当前单日累计优惠金额+本次优惠金额>=规则优惠额度,仅可优惠规则优惠额度-当前当日累计优惠金额部分金额 */
                totalSubsidy = dayQtyLimit.subtract(dayTotalDiscountAmt).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                rglog.info("当前优惠后单日累计优惠金额<{}>已超出对应规则<{}>最大优惠金额<{}>,仅可优惠<{}>!", totalDayDiscountAmt.toString(), ruleIndex, dayQtyLimit.toString(), totalSubsidy);
                //判断优惠下限金额是否大于优惠金额
                if (!StringUtil.isNullorEmpty(moneyOffAmountData.getFloorAmt())) {
                    if (CommonConstant.ZERO > totalSubsidy.compareTo(new BigDecimal(moneyOffAmountData.getFloorAmt()))) {
                        rglog.info("优惠金额<{}>小于优惠下限金额<{}>,不予优惠", totalSubsidy, moneyOffAmountData.getFloorAmt());
                        return CommonConstant.PROCESS_FAILED;
                    }
                }
                if (tmMcMoneyOffInfo.getMcType().equals(McTypeEnum.REDUCTION_FIXED_RATE.getMcTypeCode())) {
                    rglog.info("活动类型为固定折扣，优惠金额<{}>小于固定折扣所优惠的金额,不予优惠", totalSubsidy);
                    return CommonConstant.PROCESS_FAILED;
                }
            } else {
                /* 当前当日累计优惠金额+本次优惠金额<=规则单日优惠额度,正常优惠 */
                rglog.debug("当前优惠后累计优惠金额<{}>未超出对应规则<{}>最大优惠金额<{}>,正常优惠!", totalDiscountAmt.toString(), ruleIndex, budget.toString());
            }
        }

        /* 本类营销活动预算是固定的,后面添加金额校验,目前暂不校验 */

        /* 如果是银商联合的 检查指定规则层面优惠金额是否超出 */
        if (CommonConstant.SPONSOR_MIXED.equals(tmMcMoneyOffInfo.getSponsor())) {
            BigDecimal mchntSubsidy = new BigDecimal(moneyOffAmountData.getMchntSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 每商户最大优惠金额 */
            BigDecimal mchntDiscountLimitAmt = new BigDecimal(moneyOffAmountData.getMchntDiscountLimitAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 商户历史累计优惠金额 */
            BigDecimal mchntTotalAmtAcc = new BigDecimal(moneyOffAmountData.getMchntTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 商户当日累计优惠金额 */
            BigDecimal mchntDayTotalAmtAcc = new BigDecimal(moneyOffAmountData.getMchntDayTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 商户截止到当前交易前累计优惠金额 */
            BigDecimal mchntCurrentTotalAmtAcc = mchntTotalAmtAcc.add(mchntDayTotalAmtAcc).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //商户剩余可优惠额度
            BigDecimal mchntSurplusDiscountAmt = mchntDiscountLimitAmt.subtract(mchntCurrentTotalAmtAcc).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //
            BigDecimal ratio = new BigDecimal("1");
            //银行出资比例
            BigDecimal bankRatio = new BigDecimal(tmMcMoneyOffInfo.getBankBudgetRatio());


            /* 联合营销判断商户剩余可优惠额度 */
            if (CommonConstant.ZERO < mchntCurrentTotalAmtAcc.compareTo(mchntDiscountLimitAmt)) {
                /* 若当前商户累计交易金额大于商户最大优惠金额,流程结束,不予优惠 */
                rglog.info("当前商户累计优惠金额<{}>已超过银商联合活动每商户最大优惠金额<{}>,不予优惠!", mchntCurrentTotalAmtAcc.toString(), mchntDiscountLimitAmt.toString());
                return CommonConstant.PROCESS_FAILED;
            } else {
                /* 若当前商户累计交易金额不大于商户最大优惠金额,但当前商户累计交易金额加本笔交易计算的优惠额大于商户最大优惠金额,则仅优惠可优惠金额 */
                if (CommonConstant.ZERO < mchntCurrentTotalAmtAcc.add(mchntSubsidy).compareTo(mchntDiscountLimitAmt) && CommonConstant.ZERO > mchntCurrentTotalAmtAcc.compareTo(mchntDiscountLimitAmt)) {
                    //根据商户可优惠额度算出的减免类总优惠金额
                    BigDecimal mchntTotalAmt = mchntSurplusDiscountAmt.divide(ratio.subtract(bankRatio), CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    //根据商户可优惠额度算出的减免类总优惠金额应大于等于优惠下限  固定折扣类不判断优惠下限
                    if (!StringUtil.isNullorEmpty(moneyOffAmountData.getFloorAmt())) {
                        if (CommonConstant.ZERO <= mchntTotalAmt.compareTo(new BigDecimal(moneyOffAmountData.getFloorAmt()))) {
                            rglog.info("根据商户剩余可优惠额度算出的减免类总优惠金额<{}>大于等于优惠下限<{}>,可优惠", mchntTotalAmt, new BigDecimal(moneyOffAmountData.getFloorAmt()));
                            totalSubsidy = mchntTotalAmt;
                        } else {
                            rglog.info("根据商户剩余可优惠额度算出的减免类总优惠金额<{}>小于优惠下限<{}>，不予优惠", mchntTotalAmt, new BigDecimal(moneyOffAmountData.getFloorAmt()));
                            return CommonConstant.PROCESS_FAILED;
                        }
                    }
                } else if (CommonConstant.ZERO >= mchntCurrentTotalAmtAcc.add(mchntSubsidy).compareTo(mchntDiscountLimitAmt)) {
                    rglog.info("当前商户累计优惠金额<{}>未超过银商联合活动每商户最大优惠金额<{}>,继续流程!", mchntCurrentTotalAmtAcc.add(mchntSubsidy).toString(), mchntDiscountLimitAmt.toString());

                } else {
                    rglog.info("当前商户累计优惠金额<{}>已超过银商联合活动每商户最大优惠金额<{}>,不予优惠!", mchntCurrentTotalAmtAcc.add(mchntSubsidy).toString(), mchntDiscountLimitAmt.toString());
                    return CommonConstant.PROCESS_FAILED;
                }
            }
        }

        moneyOffAmountData.setTotalSubsidy(totalSubsidy.toString());

        McSubsidyData mcSubsidyData = new McSubsidyData();
        mcSubsidyData.setTotalSubsidy(totalSubsidy.toString());
        mcSubsidyData.setSponsor(tmMcMoneyOffInfo.getSponsor());
        if (CommonConstant.SPONSOR_MIXED.equals(tmMcMoneyOffInfo.getSponsor())) {
            mcSubsidyData.setBudget(tmMcMoneyOffInfo.getBudget());
            mcSubsidyData.setBankBudget(tmMcMoneyOffInfo.getBankBudget());
            mcSubsidyData.setExpectMchntQty(tmMcMoneyOffInfo.getExpectMchntQty());
            mcSubsidyData.setBankBudgetRatio(tmMcMoneyOffInfo.getBankBudgetRatio());
        }
        mcSubsidyData.setMcType(tmMcMoneyOffInfo.getMcType());

        /* 计算银行和商户出资比例 */
        int retCode = calculateBankAndMchntSubsidyRatio(mcSubsidyData);
        if (CommonConstant.PROCESS_SUCCESS != retCode) {
            rglog.info("机构<{}>的营销活动<{}>计算银行补贴金额和商户补贴金额失败,本营销活动不予优惠!", tmMcMoneyOffInfo.getInstId(), tmMcMoneyOffInfo.getMcNo());
        } else {
            rglog.info("机构<{}>的营销活动<{}>当前总优惠金额<{}>,银行优惠金额<{}>,商户优惠金额<{}>!", tmMcMoneyOffInfo.getInstId(), tmMcMoneyOffInfo.getMcNo(),
                    moneyOffAmountData.getTotalSubsidy(), moneyOffAmountData.getBankSubsidy(), moneyOffAmountData.getMchntSubsidy());

            moneyOffAmountData.setBankSubsidy(mcSubsidyData.getBankSubsidy());
            moneyOffAmountData.setMchntSubsidy(mcSubsidyData.getMchntSubsidy());
            if (CommonConstant.SPONSOR_MIXED.equals(tmMcMoneyOffInfo.getSponsor())) {
                moneyOffAmountData.setBankDiscountLimitAmt(mcSubsidyData.getBankDiscountLimitAmt());
                moneyOffAmountData.setMchntDiscountLimitAmt(mcSubsidyData.getMchntDiscountLimitAmt());
            }
        }

        return retCode;
    }

    /**
     * 卡券类营销活动交易限额处理
     *
     * @param mcCouponTxnData (合并)支付使用卡券类交易信息
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/21 09:37
     */
    private int checkCouponLimits(McCouponTxnData mcCouponTxnData) {

        /* 规则信息-顺序号 */
        String ruleIndex = mcCouponTxnData.getRuleIndex();
        /* 规则信息-卡券数量 */
        BigDecimal quantity = new BigDecimal(mcCouponTxnData.getQuantity()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
        /* 规则信息-单日核销数量 */
        BigDecimal dayRedeemLimit = new BigDecimal(mcCouponTxnData.getDayRedeemLimit()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
        /* 当前累计历史优惠笔数-优惠前 */
        BigDecimal mcTotalQtyAcc = new BigDecimal(mcCouponTxnData.getMcTotalQtyAcc()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
        /* 当前当日累计优惠笔数-优惠前 */
        BigDecimal dayTotalQtyAcc = new BigDecimal(mcCouponTxnData.getDayTotalQtyAcc()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
        /* 总累计优惠笔数-优惠前 */
        BigDecimal totalQtyAcc = mcTotalQtyAcc.add(dayTotalQtyAcc).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);

        /* 检查规则对应卡券核销总数量上限 */
        if (CommonConstant.ZERO <= totalQtyAcc.compareTo(quantity)) {
            rglog.info("当前历史累计核销卡券数量<{}>已超过规则<{}>对应的最大可核销数量<{}>,不予优惠!",
                    mcTotalQtyAcc.toString(), ruleIndex, quantity.toString());
            return CommonConstant.PROCESS_FAILED;
        }

        /* 检查单日卡券核销数量上限 */
        if (CommonConstant.ZERO <= dayTotalQtyAcc.compareTo(dayRedeemLimit)) {
            rglog.info("当前当日累计核销卡券数量<{}>已超过规则<{}>对应的当日最大可核销数量<{}>,不予优惠!",
                    dayTotalQtyAcc.toString(), ruleIndex, dayRedeemLimit.toString());
            return CommonConstant.PROCESS_FAILED;
        }
        /* 如果是银商联合的活动  判断是否超出商户最大优惠金额 */
        if (CommonConstant.SPONSOR_MIXED.equals(mcCouponTxnData.getSponsor())) {
            BigDecimal mchntSubsidy = new BigDecimal(mcCouponTxnData.getMchntSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 每商户最大优惠金额 */
            BigDecimal mchntDiscountLimitAmt = new BigDecimal(mcCouponTxnData.getMchntDiscountLimitAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 商户历史累计优惠金额 */
            BigDecimal mchntTotalAmtAcc = new BigDecimal(mcCouponTxnData.getMchntTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 商户当日累计优惠金额 */
            BigDecimal mchntDayTotalAmtAcc = new BigDecimal(mcCouponTxnData.getMchntDayTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 商户截止到当前交易前累计优惠金额 */
            BigDecimal mchntCurrentTotalAmtAcc = mchntTotalAmtAcc.add(mchntDayTotalAmtAcc).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            /* 联合营销判断商户剩余可优惠额度 */
            if (CommonConstant.ZERO < mchntCurrentTotalAmtAcc.compareTo(mchntDiscountLimitAmt)) {
                /* 若当前商户累计交易金额大于商户最大优惠金额,流程结束,不予优惠 */
                rglog.info("当前商户累计优惠金额<{}>已超过商户最大优惠金额<{}>,不予优惠!", mchntCurrentTotalAmtAcc.toString(), mchntDiscountLimitAmt.toString());
                return CommonConstant.PROCESS_FAILED;
            } else {
                /* 若当前商户累计交易金额不大于商户最大优惠金额,但当前商户累计交易金额加本笔交易计算的优惠额大于商户最大优惠金额,则不予优惠 */
                if (CommonConstant.ZERO < mchntCurrentTotalAmtAcc.add(mchntSubsidy).compareTo(mchntDiscountLimitAmt)) {
                    rglog.info("当前商户累计优惠金额<{}>已超过商户最大优惠金额<{}>,不予优惠!", mchntCurrentTotalAmtAcc.add(mchntSubsidy).toString(), mchntDiscountLimitAmt.toString());
                    return CommonConstant.PROCESS_FAILED;
                }
            }
        }

        /* 本类营销活动预算是固定的,后面添加金额校验,目前暂不校验 */

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 商户手续费优惠类营销活动交易限额处理
     *
     * @param mcMchntFeeDiscountTxnData (合并)支付使用商户手续费优惠类营销活动交易信息
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/21 09:36
     */
    private int checkMchntFeeDiscountLimits(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {

        String instId = mcMchntFeeDiscountTxnData.getInstId();
        String mcNo = mcMchntFeeDiscountTxnData.getMcNo();
        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();
        String mchntName = mcMchntFeeDiscountTxnData.getMchntName();
        String signInstId = mcMchntFeeDiscountTxnData.getSignInstId();
        //推送标志
        int pushFlag = CommonConstant.FLAG_NOT_SET;
        //不包含本笔剩余可优惠交易金额
        BigDecimal beforeDiscount;
        //包含本笔剩余可优惠交易金额
        BigDecimal afterDiscount;
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam messageSysParam = sysParamService.getSysParamInfo(globalInstId, "MOMP_MSG_PUSH", "MOMP_MSG_PUSH");

        BigDecimal orderAmt = new BigDecimal(mcMchntFeeDiscountTxnData.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //本次手续费优惠金额
        BigDecimal totalSubsidy = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeDiscount()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户统计-累计优惠金额
        BigDecimal totalAmtAcc = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户单日统计数据 具体规则-累计优惠金额
        BigDecimal totalAmtAccDay = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntDayTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        //手续费减免活动商户统计-累计交易金额
        BigDecimal txnAmtAcc = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntTxnAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户单日统计数据 具体规则-累计交易金额
        BigDecimal txnAmtAccDay = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntDayTxnAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        /* 判断单个商户营销活动优惠退出条件 */
        String terminationFlag = mcMchntFeeDiscountTxnData.getTerminationFlag();
        //优惠退出条件 手续费优惠额度
        BigDecimal remainingQuota = totalSubsidy;
        //剩余的可优惠交易额
        BigDecimal remainderDiscountAmt = orderAmt;
        //是否需要重新计算手续费
        boolean recalculate = false;

        switch (terminationFlag) {
            case CommonConstant.MCHNT_FEE_EXIT_NORMAL:
                /* 不需要判断优惠退出条件 */
                rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}>不需要判断商户优惠退出条件!可继续检查后续限额!", instId, mchntNo, mcNo);
                break;
            case CommonConstant.MCHNT_FEE_EXIT_UNDER_CONDITION:
                /* 需要判断优惠退出条件 */
                String statPeriod = mcMchntFeeDiscountTxnData.getStatPeriod();
                if (CommonConstant.FEE_EXIT_MC.equals(statPeriod) || CommonConstant.FEE_EXIT_MONTH.equals(statPeriod) ||
                        CommonConstant.FEE_EXIT_QUARTER.equals(statPeriod) || CommonConstant.FEE_EXIT_ANNUAL.equals(statPeriod)) {

                    //累计优惠笔数
                    BigDecimal totalQtyAcc9999 = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntTotalQtyAcc9999()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
                    //累计优惠金额
                    BigDecimal totalAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntTotalAmtAcc9999()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    //累计交易金额
                    BigDecimal txnAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntTxnAmtAcc9999()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    //手续费减免活动商户单日统计数据 规则为0-累计优惠笔数
                    BigDecimal totalQtyAccDayZero = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntDayTotalQtyAccZero()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
                    //手续费减免活动商户单日统计数据 规则为0-累计优惠金额
                    BigDecimal totalAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntDayTotalAmtAccZero()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    //手续费减免活动商户单日统计数据 规则为0-累计交易金额
                    BigDecimal txnAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntDayTxnAmtAccZero()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    /* 营销活动期间内判断数据 */
                    /* 单个商户优惠交易笔数上限 */
                    BigDecimal quantityLimit = new BigDecimal(mcMchntFeeDiscountTxnData.getQuantityLimit()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
                    /* 单个商户优惠交易金额上限 */
                    BigDecimal amountLimit = new BigDecimal(mcMchntFeeDiscountTxnData.getAmountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    /* 单个商户手续费优惠额上限 */
                    BigDecimal feeLimit = new BigDecimal(mcMchntFeeDiscountTxnData.getFeeLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    /* 与手续费减免活动商户统计表+手续费减免活动商户单日统计表数据对比 */
                    if (quantityLimit.compareTo(BigDecimal.ZERO) <= CommonConstant.ZERO) {
                        rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}>不需要判断单个商户优惠交易笔数上限!可继续检查后续限额!", instId, mchntNo, mcNo);
                    } else {
                        if (CommonConstant.ZERO <= quantityLimit.compareTo(totalQtyAcc9999.add(totalQtyAccDayZero).add(BigDecimal.ONE))) {
                            /* 本笔交易未超过限制,可优惠 */
                            rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}> 未超过单个商户优惠交易笔数上限!可继续检查后续限额!", instId, mchntNo, mcNo);
                        } else {
                            rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}> 已超过单个商户优惠交易笔数上限!", instId, mchntNo, mcNo);
                            return CommonConstant.PROCESS_FAILED;
                        }
                    }

                    if (amountLimit.compareTo(BigDecimal.ZERO) <= CommonConstant.ZERO) {
                        rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}>不需要判断单个商户优惠交易金额上限!可继续检查后续限额!", instId, mchntNo, mcNo);
                    } else {
                        beforeDiscount = amountLimit.subtract(txnAmtAcc9999).subtract(txnAmtAccDayZero);
                        afterDiscount = amountLimit.subtract(txnAmtAcc9999).subtract(txnAmtAccDayZero).subtract(orderAmt);
                        if (CommonConstant.ZERO <= amountLimit.compareTo(orderAmt.add(txnAmtAcc9999).add(txnAmtAccDayZero))) {
                            /* 本笔交易未超过限制,可优惠 */
                            rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}> 未超过单个商户优惠交易金额上限!可继续检查后续限额!", instId, mchntNo, mcNo);
                        } else if (CommonConstant.ZERO < amountLimit.compareTo(txnAmtAcc9999.add(txnAmtAccDayZero))) {
                            /* 不加本笔交易未超过限制，加上本笔交易超过限制*/
                            //剩余的可优惠交易金额
                            remainderDiscountAmt = amountLimit.subtract(txnAmtAcc9999.add(txnAmtAccDayZero));
                            //需要重新计算手续费
                            recalculate = true;
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}> 单个商户优惠交易金额上限<{}>,加本笔累计交易金额为<{}> 所以本笔交易剩余可优惠交易金额为<{}>!",
                                    instId, mcNo, mchntNo, amountLimit, orderAmt.add(txnAmtAcc9999).add(txnAmtAccDayZero), remainderDiscountAmt);
                        } else {
                            rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}> 已超过单个商户优惠交易金额上限<{}>!", instId, mcNo, mchntNo, amountLimit);
                            return CommonConstant.PROCESS_FAILED;
                        }
                        //优惠前剩余可优惠交易金额大于等于10000 优惠后剩余可优惠交易金额小于10000
                        if (beforeDiscount.compareTo(new BigDecimal(10000)) >= 0 && afterDiscount.compareTo(new BigDecimal(10000)) < 0) {
                            rglog.info("优惠前剩余可优惠交易金额<{}>大于等于10000,优惠后剩余可优惠交易金额<{}>小于10000。判断该行<{}>是否配置微信消息推送", beforeDiscount, afterDiscount, globalInstId);
                            //判断该行是否配置了消息推送
                            if (null != messageSysParam) {
                                rglog.info("调用短信推送");
                                //TODO 调用短信推送
                                pushFlag = CommonConstant.FLAG_SET;
                            } else {
                                rglog.info("未配置短信配送！！！");
                            }
                        }
                    }

                    if (feeLimit.compareTo(BigDecimal.ZERO) <= CommonConstant.ZERO) {
                        rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}>不需要判断单个商户手续费优惠额上限!可继续检查后续限额!", instId, mchntNo, mcNo);
                    } else {
                        if (CommonConstant.ZERO <= feeLimit.compareTo(totalSubsidy.add(totalAmtAcc9999).add(totalAmtAccDayZero))) {
                            /* 本笔交易未超过限制,可优惠 */
                            rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}> 未超过单个商户手续费优惠额上限!可继续检查后续限额!", instId, mchntNo, mcNo);
                        } else if (CommonConstant.ZERO <= feeLimit.compareTo(totalAmtAcc9999.add(totalAmtAccDayZero)) && CommonConstant.ZERO > feeLimit.compareTo(totalSubsidy.add(totalAmtAcc9999).add(totalAmtAccDayZero))) {
                            /* 本笔交易超过限制但存在剩余优惠额度,可优惠 */
                            remainingQuota = feeLimit.subtract(totalAmtAcc9999.add(totalAmtAccDayZero)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}> 本笔交易后超过单个商户手续费优惠额上限<{}>但存在可优惠额度:<{}>!", instId, mchntNo, mcNo, feeLimit, remainingQuota);
                        } else {
                            rglog.info("机构<{}> 商户<{}> 手续费优惠营销活动<{}> 已超过单个商户手续费优惠额上限<{}>!", instId, mcNo, mchntNo, feeLimit);
                            return CommonConstant.PROCESS_FAILED;
                        }
                    }
                } else {
                    /* 不需要判断优惠退出条件 */
                    rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>不需要判断商户优惠退出条件!商户<{}>可继续检查后续限额!", instId, mcNo, mchntNo);
                }
                break;
            default:
                rglog.debug("错误的优惠退出标志类型!<{}>", terminationFlag);
                return CommonConstant.PROCESS_FAILED;
        }

        //获取规则上限类型，如果规则上限是手续费金额，则需要判手续费上限
        String ruleType = mcMchntFeeDiscountTxnData.getCalRuleNo();
        //指定优惠手续费金额具体数值
        if (FeeCalTypeEnum.TYPE_13.getRuleType().equals(ruleType)) {
            MchntFeeCheckLimitService mchntFeeCheckLimitService = new MchntFeeCheckLimitService();
            Object obj = mchntFeeCheckLimitService.checkMfdRuleTotalAmtAndBudgetLimit(mcMchntFeeDiscountTxnData, remainingQuota, rglog);
            //如果返回结果为空，则已经超限，直接返回不可优惠
            if (null == obj) {
                return CommonConstant.PROCESS_FAILED;
            } else {
                McMchntFeeDiscountTxnData newMcMchntFeeDiscountTxnData = (McMchntFeeDiscountTxnData) obj;
                //如果正常返回，重新给当前计算流程中使用的实体赋优惠手续费的值
                mcMchntFeeDiscountTxnData.setMchntFeeDiscount(newMcMchntFeeDiscountTxnData.getMchntFeeDiscount());
                //重新给实收手续费赋值
                mcMchntFeeDiscountTxnData.setMchntFeeActual(new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivable()).subtract(new BigDecimal(newMcMchntFeeDiscountTxnData.getMchntFeeDiscount())).toString());
            }
        } else {
            /* 判断规则优惠上限 规则上限为优惠交易金额上限，不是优惠的手续费额上限*/
            BigDecimal discountLimit = new BigDecimal(mcMchntFeeDiscountTxnData.getDiscountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //本笔交易金额 + 周期统计累计优惠金额 + 单日统计累计优惠金额
            BigDecimal totalDiscount = remainderDiscountAmt.add(txnAmtAcc).add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("规则优惠交易金额上限<{}>,总优惠交易金额（本笔+历史）<{}>", discountLimit, totalDiscount);
            //周期统计累计优惠金额 + 单日统计累计优惠金额
            BigDecimal historyTotalDiscount = txnAmtAcc.add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //不包含本笔优惠金额
            BigDecimal discount = txnAmtAcc.add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //应收手续费
            BigDecimal mchntFeeReceivable = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
            //不包含本笔剩余可优惠交易金额
            beforeDiscount = discountLimit.subtract(txnAmtAcc).subtract(txnAmtAccDay);
            //包含本笔剩余可优惠交易金额
            afterDiscount = discountLimit.subtract(txnAmtAcc).subtract(txnAmtAccDay).subtract(orderAmt);
            if (CommonConstant.ZERO <= discountLimit.compareTo(totalDiscount)) {
                rglog.info("限额<{}>大于等于累计优惠交易金额<{}>(当前包含本笔优惠金额),可以优惠", discountLimit, totalDiscount);
                /* 限额大于等于累计优惠金额(当前包含本笔优惠金额),可以优惠 */
                if (CommonConstant.ZERO >= remainingQuota.compareTo(totalSubsidy)) {
                    totalSubsidy = remainingQuota;
                    rglog.info("总优惠金额<{}>  当前单个商户优惠退出条件<{}>", totalSubsidy, remainingQuota);
                    //重新给优惠手续费金额赋值
                    mcMchntFeeDiscountTxnData.setMchntFeeDiscount(remainingQuota.toString());
                    //重新给实收手续费赋值
                    mcMchntFeeDiscountTxnData.setMchntFeeActual(mchntFeeReceivable.subtract(remainingQuota).toString());
                }
                if (pushFlag == CommonConstant.FLAG_NOT_SET) {
                    //优惠前剩余可优惠交易金额大于等于10000 优惠后剩余可优惠交易金额小于10000
                    if (beforeDiscount.compareTo(new BigDecimal(10000)) >= 0 && afterDiscount.compareTo(new BigDecimal(10000)) < 0) {
                        rglog.info("优惠前剩余可优惠交易金额<{}>大于等于10000,优惠后剩余可优惠交易金额<{}>小于10000。判断该行<{}>是否配置微信消息推送", beforeDiscount, afterDiscount, globalInstId);
                        //判断该行是否配置了消息推送
                        if (null != messageSysParam) {
                            rglog.info("调用短信推送");
                            //TODO 调用短信推送
                        } else {
                            rglog.info("未配置短信配送！！！");
                        }
                    }
                }
                //判断是否超出预算资金
                rglog.info("判断加上本笔手续费优惠金额是否超出预算资金");
                //总预算
                BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTxnData.getBudget());
                if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
                    //总预算累计消耗金额  包含统计表+单日+本流水除本明细外的所有金额
                    BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTxnData.getMcTotalAmtAcc());
                    //加本笔明细的汇总
                    BigDecimal mcTotalAmtAccAddThisDet = mcTotalAmtAcc.add(new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeDiscount()));

                    if (CommonConstant.ZERO <= budget.compareTo(mcTotalAmtAccAddThisDet)) {
                        rglog.info("商户<{}>匹配到营销活动<{}>已累计优惠金额<{}>加上本笔优惠金额<{}>未超出总预算<{}>,给予优惠！！！", mcMchntFeeDiscountTxnData.getMchntNo(), mcMchntFeeDiscountTxnData.getMcNo(), mcTotalAmtAcc, mcTotalAmtAccAddThisDet, mcMchntFeeDiscountTxnData.getBudget());
                    } else {
                        rglog.info("加上本笔手续费优惠金额交易超出预算资金，继续判断不加本笔手续费优惠金额是否超出预算资金");
                        if (CommonConstant.ZERO >= budget.compareTo(mcTotalAmtAcc)) {
                            rglog.info("商户<{}>匹配到营销活动<{}>已累计优惠金额<{}>加上本笔优惠金额<{}>超出总预算<{}>,不予优惠！！！", mcMchntFeeDiscountTxnData.getMchntNo(), mcMchntFeeDiscountTxnData.getMcNo(), mcTotalAmtAcc, mcTotalAmtAccAddThisDet, mcMchntFeeDiscountTxnData.getBudget());
                            return CommonConstant.ONE;
                        } else {
                            rglog.info("商户<{}>匹配到营销活动<{}>已累计优惠金额<{}>加上本笔优惠金额<{}>未超过总预算<{}>,仅可优惠<{}>！！！", mcMchntFeeDiscountTxnData.getMchntNo(), mcMchntFeeDiscountTxnData.getMcNo(), mcTotalAmtAcc, mcTotalAmtAccAddThisDet, mcMchntFeeDiscountTxnData.getBudget(), budget.subtract(mcTotalAmtAcc));
                            mcMchntFeeDiscountTxnData.setMchntFeeDiscount(budget.subtract(mcTotalAmtAcc).toString());
                            //重新给实收手续费赋值
                            mcMchntFeeDiscountTxnData.setMchntFeeActual(new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivable()).subtract(budget.subtract(mcTotalAmtAcc)).toString());
                        }
                    }
                } else {
                    rglog.info("默认预算资金无上限,不判断是否超出预算资金");
                }
            } else if (CommonConstant.ZERO < discountLimit.compareTo(historyTotalDiscount)) {
                /* 不加本笔交易规则维度未超过限制，加上本笔交易超过限制*/
                //剩余的可优惠交易金额
                remainderDiscountAmt = remainderDiscountAmt.compareTo(discountLimit.subtract(historyTotalDiscount)) <= 0 ? remainderDiscountAmt : discountLimit.subtract(historyTotalDiscount);
                //需要重新计算手续费
                recalculate = true;
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>规则<{}> 商户加本次已优惠<{}> 优惠上限<{}> 已超过上限值，本次交易仅可优惠的交易金额为<{}>！",
                        instId, mcNo, mcMchntFeeDiscountTxnData.getRuleIndex(), totalDiscount, discountLimit, remainderDiscountAmt);
            } else {
                rglog.error("限额<{}>小于累计优惠金额<{}>(当前包含本笔优惠金额),不可以优惠", discountLimit, totalDiscount);
                /* 限额小于累计优惠金额(当前包含本笔优惠金额),不可以优惠 */
                return CommonConstant.PROCESS_FAILED;
            }
        }

        //需要重新计算手续费（以上判断商户剩余优惠金或者规则额度不满足本笔的交易金额）
        if (recalculate) {
            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> ，存在剩余额度，但不是所有金额都享受手续费优惠，开始重新计算手续费!", instId, mcNo);
            //重新计算手续费
            boolean recalculateMchntFee = recalculateMchntFee(mcMchntFeeDiscountTxnData, orderAmt, remainderDiscountAmt, CommonConstant.ONE_COMMON_CONSTANT);
            if (recalculateMchntFee) {
                //商户优惠交易金额 */
                mcMchntFeeDiscountTxnData.setMchntFeeDiscountTransAmt(remainderDiscountAmt.toString());
            } else {
                rglog.info("商户<{}> 重新计算手续费优惠失败，无手续费优惠!!!");
                return CommonConstant.PROCESS_FAILED;
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }


    /**
     * 判断额度用对象和数据库操作对象数据转换
     *
     * @param moneyOffAmountData 减免类营销活动金额数据
     * @param mcMoneyOffTxnData  (合并)支付使用减免类交易信息
     * @author Jinan Liu
     * @since 2020/4/16 19:51
     */
    private void copyMoneyOffMcDiscountInfo(MoneyOffAmountData moneyOffAmountData, McMoneyOffTxnData mcMoneyOffTxnData) {

        /* 营销活动编号 */
        mcMoneyOffTxnData.setMcNo(moneyOffAmountData.getMcNo());
        /* 营销活动规则顺序号 */
        mcMoneyOffTxnData.setRuleIndex(moneyOffAmountData.getRuleIndex());
        /* 营销活动类型 */
        mcMoneyOffTxnData.setMcType(moneyOffAmountData.getMcType());
        /** 满减商户清算方式 */
        mcMoneyOffTxnData.setBudgetRechargeMethod(moneyOffAmountData.getMoneyOffSettlementMethod());

        /* 减免补贴金额 */
        mcMoneyOffTxnData.setTotalSubsidy(moneyOffAmountData.getTotalSubsidy());
        /* 机构补贴金额 */
        mcMoneyOffTxnData.setBankSubsidy(moneyOffAmountData.getBankSubsidy());
        /* 商户补贴金额 */
        mcMoneyOffTxnData.setMchntSubsidy(moneyOffAmountData.getMchntSubsidy());

        /* 营销活动信息-银行每商户最大优惠金额 */
        mcMoneyOffTxnData.setBankDiscountLimitAmt(moneyOffAmountData.getBankDiscountLimitAmt());
        /* 营销活动信息-每商户最大优惠金额 */
        mcMoneyOffTxnData.setMchntDiscountLimitAmt(moneyOffAmountData.getMchntDiscountLimitAmt());

        /* 规则信息-顺序号 */
        mcMoneyOffTxnData.setRuleIndex(moneyOffAmountData.getRuleIndex());
        /* 规则信息-活动门槛 */
        mcMoneyOffTxnData.setCriteria(moneyOffAmountData.getCriteria());
        /* 规则信息-优惠力度下限 */
        mcMoneyOffTxnData.setDiscountFloor(moneyOffAmountData.getDiscountFloor());
        /* 规则信息-优惠力度上限 */
        mcMoneyOffTxnData.setDiscountCelling(moneyOffAmountData.getDiscountCelling());
        /* 规则信息-总优惠数量 */
        mcMoneyOffTxnData.setDiscountQuantity(moneyOffAmountData.getDiscountQuantity());
        /* 规则信息-单次优惠限制 */
        mcMoneyOffTxnData.setDiscountLimit(moneyOffAmountData.getDiscountLimit());
        /* 规则信息-优惠总预算 */
        mcMoneyOffTxnData.setRuleBudget(moneyOffAmountData.getRuleBudget());
        /* 规则信息-单日消耗预算 */
        mcMoneyOffTxnData.setBudgetDayLimit(moneyOffAmountData.getBudgetDayLimit());

        /* 营销活动累计-总预算累计消耗笔数 */
        mcMoneyOffTxnData.setMcTotalQtyAcc(moneyOffAmountData.getMcTotalQtyAcc());
        /* 营销活动累计-总预算累计消耗金额 */
        mcMoneyOffTxnData.setMcTotalAmtAcc(moneyOffAmountData.getMcTotalAmtAcc());

        /* 营销活动单日累计-总预算累计消耗笔数 */
        mcMoneyOffTxnData.setDayTotalQtyAcc(moneyOffAmountData.getDayTotalQtyAcc());
        /* 营销活动单日累计-总预算累计消耗金额 */
        mcMoneyOffTxnData.setDayTotalAmtAcc(moneyOffAmountData.getDayTotalAmtAcc());

        /* 营销活动商户累计-累计优惠笔数 */
        mcMoneyOffTxnData.setMchntTotalQtyAcc(moneyOffAmountData.getMchntTotalQtyAcc());
        /* 营销活动商户累计-累计优惠金额 */
        mcMoneyOffTxnData.setMchntTotalAmtAcc(moneyOffAmountData.getMchntTotalAmtAcc());

        /* 营销活动商户单日累计-累计优惠笔数 */
        mcMoneyOffTxnData.setMchntDayTotalQtyAcc(moneyOffAmountData.getMchntDayTotalQtyAcc());
        /* 营销活动商户单日累计-累计优惠金额 */
        mcMoneyOffTxnData.setMchntDayTotalAmtAcc(moneyOffAmountData.getMchntDayTotalAmtAcc());
    }

    /**
     * 使用卡券营销活动编号查询卡券营销活动信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcCouponInfo
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/17 17:22
     */
    private TMMcCouponInfo selectCouponMcInfoByPrimaryKey(String instId, String mcNo) throws Exception {

        TMMcCouponInfo tmMcCouponInfo = new TMMcCouponInfo();
        tmMcCouponInfo.setInstId(instId);
        tmMcCouponInfo.setMcNo(mcNo);

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.selectCouponMcInfoByPrimaryKey(tmMcCouponInfo);
    }

    /**
     * 检查卡券状态是否核销
     *
     * @param tmCouponInfo 卡券信息表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/17 17:43
     */
    private int checkCouponStatus(TMCouponInfo tmCouponInfo) throws Exception {

        String couponNo = tmCouponInfo.getCouponNo();
        if (StringUtil.isNullorEmpty(tmCouponInfo.getClaimUserId())) {
            rglog.error("机构<{}>卡券编号<{}>的无有效的卡券领取人,卡券状态异常,不可核销卡券!", globalInstId, couponNo, tmCouponInfo.getClaimUserId(), globalUserId);
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }
        //优惠所用id
        discountId = tmCouponInfo.getClaimUserId();
        if (userIdFlag.equals(CommonConstant.THREE_COMMON_CONSTANT)) {
            if (!discountId.equals(cardNo) && !discountId.equals(phoneNo) && !discountId.equals(wechatId) && !discountId.equals(alipayId) && !discountId.equals(coreComId)) {
                rglog.info("上送卡号<{}>和手机号<{}>,微信id<{}>,支付宝id<{}>,核心客户号<{}>不包含卡券领取人<{}>,无法享受卡券和减免优惠", cardNo, phoneNo, wechatId, alipayId, coreComId, discountId);
                throw new BizException(RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespCode(), RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespDesc());
            }
        } else if (userIdFlag.equals(CommonConstant.TWO_COMMON_CONSTANT)) {
            if (!discountId.equals(globalUserId)) {
                rglog.error("机构<{}>卡券编号<{}>的领取人为<{}>,接口上送的用户ID为<{}>,两者不同,不可核销卡券!", globalInstId, couponNo, discountId, globalUserId);
                throw new BizException(RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespCode(), RespCodeEnum.USER_TYPE_NOT_MATCH_THE_ACTIVE_STATE.getRespDesc());
            }
        } else {

        }
        mcCouponTxnData.setUserId(discountId);

        /* 判断卡券领取人是否是接口上送用户ID */
//        if(!StringUtil.isNullorEmpty(tmCouponInfo.getClaimUserId())) {
//            if(!globalUserId.equals(tmCouponInfo.getClaimUserId())) {
//                rglog.error("机构<{}>卡券编号<{}>的领取人为<{}>,接口上送的用户ID为<{}>,两者不同,不可核销卡券!", globalInstId, couponNo, tmCouponInfo.getClaimUserId(), globalUserId);
//                throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
//            }
//        } else {
//            rglog.error("机构<{}>卡券编号<{}>的无有效的卡券领取人,卡券状态异常,不可核销卡券!", globalInstId, couponNo, tmCouponInfo.getClaimUserId(), globalUserId);
//            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
//        }

        /* 判断卡券状态是否是未核销状态 */
        if (!StringUtil.isNullorEmpty(tmCouponInfo.getCouponStatus())) {
            if (!CouponStatusEnum.NOT_REDEEMED.getCouponStatusCode().equals(tmCouponInfo.getCouponStatus())) {
                rglog.error("卡券<{}>并非未核销状态<{}>,不可核销!", couponNo, tmCouponInfo.getCouponStatus());
                return CommonConstant.PROCESS_FAILED;
            }
        } else {
            rglog.error("机构<{}>卡券编号<{}>的无有效的卡券状态,卡券状态异常,不可核销卡券!", globalInstId, couponNo, tmCouponInfo.getClaimUserId(), globalUserId);
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }

        /* 判断当前交易日期是否在卡券有效期内 */
        if (!StringUtil.isNullorEmpty(tmCouponInfo.getCouponStartDate()) && !StringUtil.isNullorEmpty(tmCouponInfo.getCouponEndDate())) {

            int returnCode = MompDateUtil.checkDateRange(globalTxnDate, tmCouponInfo.getCouponStartDate(), tmCouponInfo.getCouponEndDate());
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("当前卡券核销日期<{}>并未在卡券<{}>有效期<{}>~<{}>内,不可核销!", globalTxnDate,
                        couponNo, tmCouponInfo.getCouponStartDate(), tmCouponInfo.getCouponEndDate());
                return CommonConstant.PROCESS_FAILED;
            }

        } else {
            rglog.error("机构<{}>卡券编号<{}>的无有效的卡券有效期,卡券状态异常,不可核销卡券! START_DATE=<>,END_DATE=<{}>",
                    globalInstId, couponNo, tmCouponInfo.getClaimUserId(), globalUserId, tmCouponInfo.getCouponStartDate(), tmCouponInfo.getCouponEndDate());
            throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_CP_MC_ERROR.getRespDesc());
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 使用商户编号和当前交易日期获取商户当前统计周期内已参加的商户手续费优惠营销活动统计数据
     *
     * @param instId    法人机构号
     * @param mchntNo   商户号
     * @param transDate 交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdCriteria
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 11:11
     */
    private TMStatMfdCriteria selectTMStatMfdCriteriaByUsingMchntNoAndDateRange(String instId, String mchntNo, String transDate) throws Exception {
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        return tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndDateRange(instId, mchntNo, transDate);
    }

    /**
     * 检查商户是否已退出商户手续费优惠营销活动
     * 返回0表示商户未退出
     * 返回-1表示商户已退出
     *
     * @param flag 商户退出标志
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/20 13:55
     */
    private int checkMchntExitFlag(String flag) {

        if (CommonConstant.MC_NOT_EXIT_FLAG.equals(flag)) {
            rglog.info("未退出营销活动");
            return CommonConstant.PROCESS_SUCCESS;
        } else {
            rglog.info("已退出营销活动");
            return CommonConstant.PROCESS_FAILED;
        }
    }

    /**
     * 检查存量商户是否已达标
     * 返回0表示商户已达标
     * 返回-1表示商户未达标
     *
     * @param flag 存量商户达标标志
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020-08-06 01:04
     */
    private int checkStockMchntCriteriaFlag(String flag) {

        if (CommonConstant.CRITERIA_FLAG_SET.equals(flag)) {
            rglog.info("存量商户当前统计周期已达标,可以优惠");
            return CommonConstant.PROCESS_SUCCESS;
        } else {
            rglog.info("存量商户当前统计周期未达标,不可优惠");
            return CommonConstant.PROCESS_FAILED;
        }
    }

    /**
     * 手续费减免达标数据统计表数据赋值
     *
     * @param tmStatMfdCriteria         手续费减免达标数据统计表
     * @param mcMchntFeeDiscountTxnData (合并)支付使用商户手续费优惠类营销活动交易信息
     * @author Jinan Liu
     * @since 2020/4/20 14:51
     */
    private void convertMchntFeeDiscountCriteria(TMStatMfdCriteria tmStatMfdCriteria, McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) {

        /* 营销活动编号 */
        mcMchntFeeDiscountTxnData.setMcNo(tmStatMfdCriteria.getMcNo());
        /* 统计起始日期 */
        mcMchntFeeDiscountTxnData.setPeriodStartDate(tmStatMfdCriteria.getPeriodStartDate());
        /* 统计结束日期 */
        mcMchntFeeDiscountTxnData.setPeriodEndDate(tmStatMfdCriteria.getPeriodEndDate());
        /* 记录索引 */
        mcMchntFeeDiscountTxnData.setRecIndex(tmStatMfdCriteria.getRecIndex());
        /* 达标前手续费优惠规则 */
        mcMchntFeeDiscountTxnData.setBeforeFlag(tmStatMfdCriteria.getBeforeFlag());
        /* 达标后手续费优惠规则 */
        mcMchntFeeDiscountTxnData.setAfterFlag(tmStatMfdCriteria.getAfterFlag());
        /* 商户新增标志 */
        mcMchntFeeDiscountTxnData.setNewMchntCriteriaFlag(tmStatMfdCriteria.getNewMchntFlag());
        /* 商户新增日期 */
        mcMchntFeeDiscountTxnData.setNewMchntDate(tmStatMfdCriteria.getNewMchntDate());
        /* 新增商户有效起始日期 */
        mcMchntFeeDiscountTxnData.setNewMchntStartDate(tmStatMfdCriteria.getNewMchntStartDate());
        /* 新增商户有效结束日期 */
        mcMchntFeeDiscountTxnData.setNewMchntEndDate(tmStatMfdCriteria.getNewMchntEndDate());
        /* 优惠退出状态 */
        mcMchntFeeDiscountTxnData.setExitDiscountStatus(tmStatMfdCriteria.getExitDiscountStatus());
        /* 存量商户支持类型 */
        mcMchntFeeDiscountTxnData.setCriteriaType(tmStatMfdCriteria.getCriteriaType());
        /* 存量商户当前统计值 */
        mcMchntFeeDiscountTxnData.setCriteriaValue(tmStatMfdCriteria.getCriteriaValue());
        /* 存量商户达标标志 */
        mcMchntFeeDiscountTxnData.setCriteriaFlag(tmStatMfdCriteria.getCriteriaFlag());
        /* 存量商户达标日期 */
        mcMchntFeeDiscountTxnData.setCriteriaDate(tmStatMfdCriteria.getCriteriaDate());
        /* 达标前手续费返现打款状态 */
        mcMchntFeeDiscountTxnData.setPreCashbackStatus(tmStatMfdCriteria.getPreCashbackStatus());
        /* 达标前手续费返现打款金额 */
        mcMchntFeeDiscountTxnData.setPreCashbackAmt(tmStatMfdCriteria.getPreCashbackAmt());
        /* 达标后手续费返现打款状态 */
        mcMchntFeeDiscountTxnData.setPostCashbackStatus(tmStatMfdCriteria.getPostCashbackStatus());
        /* 达标后手续费返现打款金额 */
        mcMchntFeeDiscountTxnData.setPostCashbackAmt(tmStatMfdCriteria.getPostCashbackAmt());
        /* 达标统计表数据创建时间 */
        mcMchntFeeDiscountTxnData.setMfdCriteriaCreateTime(tmStatMfdCriteria.getCreateTime());
        /* 商户优惠上限值	 */
        mcMchntFeeDiscountTxnData.setMrctDisUpLmtVal(tmStatMfdCriteria.getMrctDisUpLmtVal());
    }

    /**
     * 商户手续费优惠营销活动信息转换
     *
     * @param tmMcMchntFeeDiscountInfo  商户手续费减免类营销活动信息表
     * @param mcMchntFeeDiscountTxnData (合并)支付使用商户手续费优惠类营销活动交易信息
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 17:14
     */
    private void convertMchntFeeDiscountMcInfo(TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo, McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {

        /* 营销活动编号 */
        mcMchntFeeDiscountTxnData.setMcNo(tmMcMchntFeeDiscountInfo.getMcNo());
        /* 营销活动名称 */
        mcMchntFeeDiscountTxnData.setMcName(tmMcMchntFeeDiscountInfo.getMcName());
        /* 营销活动类型 */
        mcMchntFeeDiscountTxnData.setMcType(tmMcMchntFeeDiscountInfo.getMcType());
        /* 营销活动状态 */
        mcMchntFeeDiscountTxnData.setMcStatus(tmMcMchntFeeDiscountInfo.getMcStatus());
        /* 活动起始日期 */
        mcMchntFeeDiscountTxnData.setMcStartDate(tmMcMchntFeeDiscountInfo.getMcStartDate());
        /* 活动截止日期 */
        mcMchntFeeDiscountTxnData.setMcEndDate(tmMcMchntFeeDiscountInfo.getMcEndDate());
        /* 活动结束日期 */
        mcMchntFeeDiscountTxnData.setMcActualEndDate(tmMcMchntFeeDiscountInfo.getMcActualEndDate());
        /* 存量商户达标条件 */
        mcMchntFeeDiscountTxnData.setStockMchntFlag(tmMcMchntFeeDiscountInfo.getStockMchntFlag());
        /* 存量商户支持类型 */
        mcMchntFeeDiscountTxnData.setStockMchntType(tmMcMchntFeeDiscountInfo.getStockMchntType());
        /* 有效交易下限 */
        mcMchntFeeDiscountTxnData.setEffectiveLimit(tmMcMchntFeeDiscountInfo.getEffectiveLimit());
        /* 新增商户活动标志 */
        mcMchntFeeDiscountTxnData.setNewMchntFlag(tmMcMchntFeeDiscountInfo.getNewMchntFlag());
        /* 新增商户免手续费周期 */
        mcMchntFeeDiscountTxnData.setNewMchntPeriod(tmMcMchntFeeDiscountInfo.getNewMchntPeriod());
        /* 新增商户免手续费交易额上限 */
        mcMchntFeeDiscountTxnData.setNewMchntAmountLimit(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());
        /* 新增商户周期顺延标志 */
        mcMchntFeeDiscountTxnData.setPostponeFlag(tmMcMchntFeeDiscountInfo.getPostponeFlag());
        /* 达标前手续费优惠规则 */
        mcMchntFeeDiscountTxnData.setBeforeFlag(tmMcMchntFeeDiscountInfo.getBeforeFlag());
        /* 达标后手续费优惠规则 */
        mcMchntFeeDiscountTxnData.setAfterFlag(tmMcMchntFeeDiscountInfo.getAfterFlag());

        /* 赋值手续费优惠方式 */
        if (CommonConstant.FEE_REAL_TIME_DISCOUNT_FLAG.equals(tmMcMchntFeeDiscountInfo.getAfterFlag())) {
            /* 实时返现 */
            mcMchntFeeDiscountTxnData.setMchntFeeDiscountMethod(CommonConstant.FEE_POSTPONE_DISCOUNT_FLAG);
        } else {
            /* 事后返现 */
            mcMchntFeeDiscountTxnData.setMchntFeeDiscountMethod(CommonConstant.FEE_REAL_TIME_DISCOUNT_FLAG);
        }

        /* 优惠退出标志 */
        mcMchntFeeDiscountTxnData.setTerminationFlag(tmMcMchntFeeDiscountInfo.getTerminationFlag());
        /* 统计周期 */
        mcMchntFeeDiscountTxnData.setStatPeriod(tmMcMchntFeeDiscountInfo.getStatPeriod());
        /* 单个商户优惠交易笔数上限 */
        mcMchntFeeDiscountTxnData.setQuantityLimit(tmMcMchntFeeDiscountInfo.getQuantityLimit());
        /* 单个商户优惠交易金额上限 */
        mcMchntFeeDiscountTxnData.setAmountLimit(tmMcMchntFeeDiscountInfo.getAmountLimit());
        /* 单个商户手续费优惠额上限 */
        mcMchntFeeDiscountTxnData.setFeeLimit(tmMcMchntFeeDiscountInfo.getFeeLimit());
        /* 预算充值方式 */
        mcMchntFeeDiscountTxnData.setBudgetRechargeMethod(tmMcMchntFeeDiscountInfo.getBudgetRechargeMethod());
        /* 预算 */
        mcMchntFeeDiscountTxnData.setBudget(tmMcMchntFeeDiscountInfo.getBudget());
        /* 审批状态 */
        mcMchntFeeDiscountTxnData.setAuditStatus(tmMcMchntFeeDiscountInfo.getAuditStatus());
        /* 新增商户免费额度类型 */
        mcMchntFeeDiscountTxnData.setNewmrctFreeLmtTyp(tmMcMchntFeeDiscountInfo.getNewmrctFreeLmtTyp());
    }

    /**
     * 商户手续费优惠营销活动规则信息转换
     *
     * @param tmMcMchntFeeDiscountRuleInfo 商户手续费减免类营销活动规则信息表
     * @param mcMchntFeeDiscountTxnData    (合并)支付使用商户手续费优惠类营销活动交易信息
     * @author Jinan Liu
     * @since 2020/4/20 20:47
     */
    private void convertMchntFeeDiscountMcRuleInfo(TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo, McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) {

        /* 顺序号 */
        mcMchntFeeDiscountTxnData.setRuleIndex(tmMcMchntFeeDiscountRuleInfo.getRuleIndex());
        /* 控制下限 */
        mcMchntFeeDiscountTxnData.setCriteriaFloor(tmMcMchntFeeDiscountRuleInfo.getCriteriaFloor());
        /* 控制上限 */
        mcMchntFeeDiscountTxnData.setCriteriaCelling(tmMcMchntFeeDiscountRuleInfo.getCriteriaCelling());
        /* 优惠周期 */
        mcMchntFeeDiscountTxnData.setDiscountPeriod(tmMcMchntFeeDiscountRuleInfo.getDiscountPeriod());
        /* 优惠类型 */
        mcMchntFeeDiscountTxnData.setDiscountType(tmMcMchntFeeDiscountRuleInfo.getDiscountType());
        /* 优惠力度 */
        mcMchntFeeDiscountTxnData.setDiscount(tmMcMchntFeeDiscountRuleInfo.getDiscount());
        /* 计算规则编号 */
        mcMchntFeeDiscountTxnData.setCalRuleNo(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo());
        /* 优惠上限 */
        mcMchntFeeDiscountTxnData.setDiscountLimit(tmMcMchntFeeDiscountRuleInfo.getDiscountLimit());
    }

    /**
     * 商户手续费优惠营销活动计算规则信息转换
     *
     * @param tmPlatCalRule             计算规则码表
     * @param mcMchntFeeDiscountTxnData (合并)支付使用商户手续费优惠类营销活动交易信息
     * @author Jinan Liu
     * @since 2020/4/20 21:06
     */
    private void convertMchntFeeDiscountMcCalRuleInfo(TMPlatCalRule tmPlatCalRule, McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) {

        /* 规则编号 */
        mcMchntFeeDiscountTxnData.setRuleNo(tmPlatCalRule.getRuleNo());
        /* 业务类型 */
        mcMchntFeeDiscountTxnData.setBizType(tmPlatCalRule.getBizType());
        /* 规则类型 */
        mcMchntFeeDiscountTxnData.setRuleType(tmPlatCalRule.getRuleType());
        /* 规则描述 */
        mcMchntFeeDiscountTxnData.setRuleContent(tmPlatCalRule.getRuleContent());
        /* 处理服务类名 */
        mcMchntFeeDiscountTxnData.setServiceName(tmPlatCalRule.getServiceName());
        /* 规则启用状态 */
        mcMchntFeeDiscountTxnData.setRuleStatus(tmPlatCalRule.getRuleStatus());
    }

    /**
     * 根据计算规则计算当前商户手续费优惠限额
     *
     * @param mcMchntFeeDiscountTxnData (合并)支付使用商户手续费优惠类营销活动交易信息
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/10 02:41
     */
    private void calculateMchntFeeDiscountLimit(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {

        String instId = mcMchntFeeDiscountTxnData.getInstId();
        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();

        String month = DateUtil.getFutureMonDay(CommonConstant.MINUS_ONE).substring(0, 6);
        rglog.debug("INST_ID=<{}>, MCHNT_NO=<{}>, MONTH=<{}>", instId, mchntNo, month);

        //商户上月日均余额直接取达标统计表中的当前统计值
        String mchntDeposit = mcMchntFeeDiscountTxnData.getCriteriaValue();

        BigDecimal TWO = new BigDecimal("2");
        BigDecimal HUNDARD_1 = new BigDecimal("125");
        BigDecimal HUNDARD_5 = new BigDecimal("500");
        BigDecimal THOUSAND_30 = new BigDecimal("30000");
        BigDecimal THOUSAND_50 = new BigDecimal("50000");
        BigDecimal THOUSAND_100 = new BigDecimal("100000");

        BigDecimal deposit = new BigDecimal(mchntDeposit).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal tenThousand = new BigDecimal("10000").setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal discountLimit;

        String ruleType = mcMchntFeeDiscountTxnData.getRuleType();
        if (null != ruleType) {
            switch (FeeCalTypeEnum.getByValue(ruleType)) {
                case TYPE_0:
                    /* 无上限 */
                    return;
                case TYPE_1:
                    /* 指定具体数值 */
                    return;
                case TYPE_2:
                    /* 上月日均存款万位取整+3万 */
                    discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_3:
                    /* 上月日均存款*2+3万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_4:
                    /* 上月日均存款万位取整+5万 */
                    discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_5:
                    /* 上月日均存款*2+5万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_50);
                    break;
                case TYPE_6:
                    /* 上月日均存款每10万优惠125元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_1);
                    break;
                case TYPE_7:
                    /* 上月日均存款每10万优惠500元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_5);
                    break;
                case TYPE_8:
                    /* 上月日均存款 */
                    discountLimit = deposit;
                    break;
                case TYPE_9:
                    /* 上月日均存款每万元取整*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+3万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_10:
                    /* 上月日均存款每万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+5万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_11:
                    /* 上月日均存款每十万元*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+3万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_12:
                    /* 上月日均存款每十万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+5万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_50);
                    break;
                default:
                    discountLimit = BigDecimal.ZERO;
                    rglog.error("营销活动<{}> 规则类型<{}> 手续费优惠限额计算规则类型错误!!!!!!", mcMchntFeeDiscountTxnData.getMcNo(), FeeCalTypeEnum.getByValue(ruleType));
            }
            rglog.info("规则层面优惠交易金额上限 DISCOUNT_LIMIT=<{}>", discountLimit.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
            mcMchntFeeDiscountTxnData.setDiscountLimit(discountLimit.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        } else {
            mcMchntFeeDiscountTxnData.setDiscountLimit(CommonConstant.ZERO_AMOUNT);
        }

    }


    /**
     * 存量商户根据
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountRuleInfo 商户手续费减免类营销活动规则信息表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 18:01
     */
    private List<TMMcMchntFeeDiscountRuleInfo> getMchntFeeDiscountMcRuleInfo(String instId, String mcNo) throws Exception {

        McRuleInfoMapper mcRuleInfoMapper = new McRuleInfoMapperImpl();
        return mcRuleInfoMapper.selectMchntFeeDiscountRuleInfoList(instId, mcNo);
    }

    /**
     * 获取商户手续费营销活动的活动规则对应的计算规则
     *
     * @param instId 法人机构号
     * @param ruleNo 规则编号
     * @return cc.rengu.igas.momp.common.entity.TMPlatCalRule 计算规则码表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 21:01
     */
    private TMPlatCalRule selectCalculationRuleInfoByPK(String instId, String ruleNo) throws Exception {

        TMPlatCalRuleMapper tmPlatCalRuleMapper = new TMPlatCalRuleMapperImpl();
        return tmPlatCalRuleMapper.selectCalculationRuleInfoByPrimaryKey(instId, ruleNo);
    }

    /**
     * 计算优惠手续费和实收手续费
     *
     * @param mcMchntFeeDiscountTxnData (合并)支付使用商户手续费优惠类营销活动交易信息
     * @return java.lang.String 手续费优惠金额
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 21:42
     */
    private String calculateMchntFeeDiscountSubsidy(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {

        /* 判断计算类型 */
        BigDecimal thousand = new BigDecimal(CommonConstant.THOUSAND);
        /* 手续费收取方式 */
        String feeInputMode = mcMchntFeeDiscountTxnData.getFeeInputMode();
        /* 应收手续费 */
        BigDecimal mchntFeeReceivable = new BigDecimal(CommonConstant.ZERO_AMOUNT);
        /* 订单金额 */
        BigDecimal orderAmt = new BigDecimal(mcMchntFeeDiscountTxnData.getOrderAmt());

        /* 手续费优惠类型 */
        String discountType = mcMchntFeeDiscountTxnData.getDiscountType();
        /* 优惠手续费 */
        BigDecimal mchntFeeDiscount =  new BigDecimal(CommonConstant.ZERO_AMOUNT);
        /* 实收手续费 */
        BigDecimal mchntFeeActual = mchntFeeReceivable;
        /* 优惠力度 */
        BigDecimal discount;

        //当手续费收取方式feeInputMode为手工输入按固定金额时，接口不上送费率值，在这默认赋值为0；
        if (CommonConstant.TWO_COMMON_CONSTANT.equals(feeInputMode))
            mcMchntFeeDiscountTxnData.setMchntFeeReceivableRate(CommonConstant.ZERO_COMMON_CONSTANT);

        //当前手续费收取方式-使用现有费率时，接口不上送 商户应收手续费金额	mchntFeeReceivable  和 商户应收手续费费率	mchntFeeReceivableRate
        if (!CommonConstant.FEE_MODE_LADDER.equals(feeInputMode) && !StringUtil.isNullorEmpty(mcMchntFeeDiscountTxnData.getMchntFeeReceivable())) {
            mchntFeeReceivable = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
        }
        if (!StringUtil.isNullorEmpty(feeInputMode)) {
            switch (feeInputMode) {
                case CommonConstant.FEE_MODE_LADDER:
                    /* 使用现有费率 */
                    rglog.error("不支持配置费率模板方式的商户手续费优惠计算!");
                    mchntFeeDiscount = BigDecimal.ZERO;
                    mchntFeeActual = mchntFeeReceivable;
                    break;
                case CommonConstant.FEE_MODE_RATE:
                    /* 手工输入按比率 */
                    switch (discountType) {
                        case CommonConstant.MCHNT_FEE_FREE:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-免手续费!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            /* 手续费全免,实收为0,优惠=应收 */
                            mchntFeeDiscount = mchntFeeReceivable;
                            mchntFeeActual = BigDecimal.ZERO;
                            break;
                        case CommonConstant.MCHNT_FEE_DISCOUNT:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-费率打折!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            /* 费率打折,实收=应收*费率*折扣,优惠=应收-实收 */
                            discount = new BigDecimal(mcMchntFeeDiscountTxnData.getDiscount());
                            mchntFeeActual = mchntFeeReceivable.multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            mchntFeeDiscount = mchntFeeReceivable.subtract(mchntFeeActual);
                            break;
                        case CommonConstant.MCHNT_FEE_FIXED_RATE:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-固定费率!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            /* 固定费率,实收=订单金额*优惠费率,优惠=应收-实收 */
                            //判断固定费率和应收费率的大小，如果固定费率大于应收，则没有优惠
                            if (new BigDecimal(mcMchntFeeDiscountTxnData.getDiscount()).compareTo(new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivableRate())) >= CommonConstant.ZERO) {
                                rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,活动固定费率<{}> >= 应收费率<{}>，无手续费优惠",
                                        mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, mcMchntFeeDiscountTxnData.getDiscount(), mcMchntFeeDiscountTxnData.getMchntFeeReceivableRate());
                                mchntFeeDiscount = BigDecimal.ZERO;
                                mchntFeeActual = mchntFeeReceivable;
                            } else {
                                discount = new BigDecimal(mcMchntFeeDiscountTxnData.getDiscount()).divide(thousand);
                                mchntFeeActual = orderAmt.multiply(discount).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                                mchntFeeDiscount = mchntFeeReceivable.subtract(mchntFeeActual);
                            }
                            break;
                        default:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-优惠类型异常!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            mchntFeeDiscount = BigDecimal.ZERO;
                            mchntFeeActual = mchntFeeReceivable;
                            break;
                    }
                    break;
                case CommonConstant.FEE_MODE_FIXED_AMT:
                    /* 手工输入按固定金额 */
                    switch (discountType) {
                        case CommonConstant.MCHNT_FEE_FREE:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-免手续费!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            /* 手续费全免,实收为0,优惠=应收 */
                            mchntFeeDiscount = mchntFeeReceivable;
                            mchntFeeActual = BigDecimal.ZERO;
                            break;
                        case CommonConstant.MCHNT_FEE_DISCOUNT:
                        case CommonConstant.MCHNT_FEE_FIXED_RATE:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-不可使用费率打折或固定费率的商户手续费优惠方式!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            /* 手工输入按固定金额,不支持费率打折或固定费率的优惠方式 */
                            mchntFeeDiscount = BigDecimal.ZERO;
                            mchntFeeActual = mchntFeeReceivable;
                            break;
                        default:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-优惠类型异常!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            mchntFeeDiscount = BigDecimal.ZERO;
                            mchntFeeActual = mchntFeeReceivable;
                            break;
                    }
                    break;
                case CommonConstant.FEE_MODE_RATE_AMT:
                    /* 手工输入按比率+封顶值 */
                    switch (discountType) {
                        case CommonConstant.MCHNT_FEE_FREE:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-免手续费!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            /* 手续费全免,实收为0,优惠=应收 */
                            mchntFeeDiscount = mchntFeeReceivable;
                            mchntFeeActual = BigDecimal.ZERO;
                            break;
                        case CommonConstant.MCHNT_FEE_DISCOUNT:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-费率打折!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            /* 费率打折,实收=min(订单金额*费率*折扣,应收),优惠=应收-实收 */
                            //应收手续费费率
                            BigDecimal mchntFeeReceivableRate = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivableRate()).divide(thousand);
                            discount = new BigDecimal(mcMchntFeeDiscountTxnData.getDiscount());
                            mchntFeeActual = orderAmt.multiply(mchntFeeReceivableRate).multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            mchntFeeActual = mchntFeeActual.min(mchntFeeReceivable);
                            mchntFeeDiscount = mchntFeeReceivable.subtract(mchntFeeActual);
                            break;
                        case CommonConstant.MCHNT_FEE_FIXED_RATE:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-固定费率!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            /* 固定费率,实收=min(订单金额*优惠费率,应收),优惠=应收-实收 */
                            //判断固定费率和应收费率的大小，如果固定费率大于应收，则没有优惠
                            if (new BigDecimal(mcMchntFeeDiscountTxnData.getDiscount()).compareTo(new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivableRate())) >= CommonConstant.ZERO) {
                                rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,活动固定费率<{}> >= 应收费率<{}>，无手续费优惠",
                                        mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, mcMchntFeeDiscountTxnData.getDiscount(), mcMchntFeeDiscountTxnData.getMchntFeeReceivableRate());
                                mchntFeeDiscount = BigDecimal.ZERO;
                                mchntFeeActual = mchntFeeReceivable;
                            } else {
                                discount = new BigDecimal(mcMchntFeeDiscountTxnData.getDiscount()).divide(thousand);
                                mchntFeeActual = orderAmt.multiply(discount).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                                mchntFeeActual = mchntFeeActual.min(mchntFeeReceivable);
                                mchntFeeDiscount = mchntFeeReceivable.subtract(mchntFeeActual);
                            }
                            break;
                        default:
                            rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-优惠类型异常!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode, discountType);
                            mchntFeeDiscount = BigDecimal.ZERO;
                            mchntFeeActual = mchntFeeReceivable;
                            break;
                    }
                    break;
                default:
                    rglog.info("商户<{}>,手续费收取方式<{}>-手续费收取方式异常!", mcMchntFeeDiscountTxnData.getMchntNo(), feeInputMode);
                    mchntFeeDiscount = BigDecimal.ZERO;
                    mchntFeeActual = mchntFeeReceivable;
                    break;
            }
        }
        rglog.info("商户<{}>,计算的手续费优惠<{}>,实收<{}>", mcMchntFeeDiscountTxnData.getMchntNo(), mchntFeeDiscount, mchntFeeActual);
        mcMchntFeeDiscountTxnData.setMchntFeeDiscount(mchntFeeDiscount.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        mcMchntFeeDiscountTxnData.setMchntFeeActual(mchntFeeActual.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());

        return mchntFeeDiscount.toString();
    }

    /**
     * 取对客类营销活动各维度统计数据
     *
     * @param object (合并)支付使用XX类营销活动交易信息
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 20:18
     */
    private int fetchAllToClientMcQuotaData(Object object) throws Exception {

        String mcNo;
        String mchntNo;
        String ruleIndex;
        int batchStatus;
        String mcStartDate;
        String sponsor = "";
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String mcType;

        if (object instanceof MoneyOffAmountData) {
            mcNo = ((MoneyOffAmountData) object).getMcNo();
            mchntNo = ((MoneyOffAmountData) object).getMchntNo();
            ruleIndex = ((MoneyOffAmountData) object).getRuleIndex();
            mcStartDate = ((MoneyOffAmountData) object).getMcStartDate();
            sponsor = ((MoneyOffAmountData) object).getSponsor();
            mcType = ((MoneyOffAmountData) object).getMcType();
        } else if (object instanceof McCouponTxnData) {
            mcNo = ((McCouponTxnData) object).getMcNo();
            mchntNo = ((McCouponTxnData) object).getMchntNo();
            ruleIndex = ((McCouponTxnData) object).getRuleIndex();
            mcStartDate = ((McCouponTxnData) object).getMcStartDate();
            sponsor = ((McCouponTxnData) object).getSponsor();
            mcType = ((McCouponTxnData) object).getMcType();
        } else {
            rglog.error("错误的对象类型<{}>", object.getClass());
            return CommonConstant.PROCESS_FAILED;
        }

        /* 查询对客户营销活动统计表数据 */
        TMStat2C tmStat2C = selectToClientMcLevelStatistics(globalInstId, mcNo, ruleIndex);
        if (null == tmStat2C) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>对客户营销活动统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            tmStat2C = new TMStat2C();
            tmStat2C.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2C.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询对客户营销活动单日统计表数据 */
        TMStat2CDay tmStat2CDay = selectToClientMcDayStatistics(globalInstId, mcNo, ruleIndex, globalTxnDate);
        if (null == tmStat2CDay) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>对客户营销活动单日统计表数据查询失败!", globalInstId, mcNo, ruleIndex);
            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStat2CDay = new TMStat2CDay();
            tmStat2CDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "Custom" + globalInstId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            TMStat2CDay tmStat2CDayNew = selectToClientMcDayStatistics(globalInstId, mcNo, ruleIndex, batchDate);
            if (null == tmStat2CDayNew) {
                rglog.error("查询用户<{}>活动<{}>对客活动单日统计表 数据查询失败!", mcNo);
                tmStat2CDayNew = new TMStat2CDay();
                tmStat2CDayNew.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStat2CDayNew.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copytmStat2CData(tmStat2C, tmStat2CDayNew);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /* 对象赋值 */
        if (object instanceof MoneyOffAmountData || object instanceof McCouponTxnData) {
            copyMoneyOffToClientStatData(tmStat2C, object);
            copyMoneyOffToClientSingleDayStatData(tmStat2CDay, object);
        } else {
            rglog.error("错误的对象类型<{}>", object.getClass().getClass());
            return CommonConstant.PROCESS_FAILED;
        }

        //不是银行全资的 需要获取商户统计信息
        if (!CommonConstant.SPONSOR_BANK.equals(sponsor)) {
            /* 查询对客户营销活动商户统计表数据 */
            TMStat2CMchnt tmStat2CMchnt = selectToClientMcMchntStatistics(globalInstId, mcNo, mchntNo);
            if (null == tmStat2CMchnt) {
                rglog.info("机构<{}>的商户<{}>的减免类营销活动<{}>的对客户营销活动商户统计表数据查询失败!", globalInstId, mchntNo, mcNo);
                /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
                tmStat2CMchnt = new TMStat2CMchnt();
                tmStat2CMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStat2CMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

            }
            statPrimaryKey = "MchntStat" + globalInstId + "_" + mcNo;
            tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
            //批次表为空，从来没执行过批量任务
            if (null == tmStatBak) {
                //从来没执行过批量任务，则从活动开始的第一天开始取数据
                batchDate = mcStartDate;
            } else {
                batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
            }
            //批量处理的日期小于昨天的日期，则需要取之前的数据
            while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
                //获取的数据累加到活动统计中
                TMStat2CMchntDay tmStat2CMchntDay = selectToClientMcMchntDayStatistics(globalInstId, mcNo, mchntNo, batchDate);
                if (null == tmStat2CMchntDay) {
                    rglog.error("查询用户<{}>活动<{}>对客活动单日统计表 数据查询失败!", mcNo);
                    tmStat2CMchntDay = new TMStat2CMchntDay();
                    tmStat2CMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                    tmStat2CMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                }
                copytmStat2CMchntData(tmStat2CMchnt, tmStat2CMchntDay);
                //将批次日期加一天继续判断
                batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
            }
            /* 查询对客户营销活动商户单日统计表数据 */
            TMStat2CMchntDay tmStat2CMchntDay = selectToClientMcMchntDayStatistics(globalInstId, mcNo, mchntNo, globalTxnDate);
            if (null == tmStat2CMchntDay) {
                rglog.info("机构<{}>的商户<{}>的减免类营销活动<{}>的对客户营销活动商户统计表数据查询失败!", globalInstId, mchntNo, mcNo);
                /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
                tmStat2CMchntDay = new TMStat2CMchntDay();
                tmStat2CMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStat2CMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }

            /* 对象赋值 */
            if (object instanceof MoneyOffAmountData || object instanceof McCouponTxnData) {
                copyMoneyOffToClientMchntStatData(tmStat2CMchnt, object);
                copyMoneyOffToClientMchntDayStatData(tmStat2CMchntDay, object);
            } else {
                rglog.error("错误的对象类型<{}>", object.getClass().getClass());
                return CommonConstant.PROCESS_FAILED;
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 取商户手续费优惠类营销活动各维度统计数据
     *
     * @param object (合并)支付使用商户手续费优惠类营销活动交易信息
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 20:22
     */
    private int fetchAllMchntFeeDiscountMcQuotaData(Object object) throws Exception {
        //规则维度批量处理状态
        int batchStatus = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        String instId = ((McMchntFeeDiscountTxnData) object).getInstId();
        String mcNo = ((McMchntFeeDiscountTxnData) object).getMcNo();
        String mchntNo = ((McMchntFeeDiscountTxnData) object).getMchntNo();
        String transDate = ((McMchntFeeDiscountTxnData) object).getTransDate();
        String periodStartDate = ((McMchntFeeDiscountTxnData) object).getPeriodStartDate();
        String periodEndDate = ((McMchntFeeDiscountTxnData) object).getPeriodEndDate();
        String mcStartDate = ((McMchntFeeDiscountTxnData) object).getMcStartDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String ruleIndex = ((McMchntFeeDiscountTxnData) object).getRuleIndex();
        String mcType = ((McMchntFeeDiscountTxnData) object).getMcType();

        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, transDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, transDate);
        if (null == tmStatMfdMchntDayRuleZero) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
            tmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户统计表数据  查询规则为9999的数据，这个统计的是营销活动配置商户退出条件时，统计周期内的所有规则的统计值*/
        TMStatMfdMchnt tmStatMfdMchnt9999 = selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, CommonConstant.RULE_NINE, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchnt9999) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, CommonConstant.RULE_NINE);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt9999 = new TMStatMfdMchnt();
            tmStatMfdMchnt9999.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDayRuleZero) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
                newtmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
                copyMchntStatMfdData(tmStatMfdMchnt9999, newtmStatMfdMchntDayRuleZero);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, globalTxnDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay2 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, batchDate);
            if (null == tmStatMfdDay2) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2 = new TMStatMfdDay();
                tmStatMfdDay2.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay2);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }


        //更新本笔交易累计金额
        List<TMStatMfdDay> newStatMfdDayList = statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList());
        //存在本笔交易同一活动数据
        if (newStatMfdDayList.size() > 0) {
            //全局变量手续费营销活动单日统计表数据更新已优惠金额
            TMStatMfdDay tmStatMfdToday = newStatMfdDayList.get(0);
            BigDecimal dayTotalAmtAcc = new BigDecimal(tmStatMfdToday.getTotalAmtAcc());
            statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList()).get(0).setTotalAmtAcc(dayTotalAmtAcc.add(new BigDecimal(((McMchntFeeDiscountTxnData) object).getMchntFeeDiscount())).toString());

        } else {
            //如果不存在 将子订单set
            TMStatMfdDay tmStatMfdToday = new TMStatMfdDay();
            tmStatMfdToday.setTotalAmtAcc(((McMchntFeeDiscountTxnData) object).getMchntFeeDiscount());
            tmStatMfdToday.setInstId(instId);
            tmStatMfdToday.setMcNo(mcNo);
            statMfdDayList.add(tmStatMfdToday);
        }

        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, object);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, object);
        copyMchntFeeDiscountMchntStat9999Data(tmStatMfdMchnt9999, object);
        copyMchntFeeDiscountMchntDayZeroStatData(tmStatMfdMchntDayRuleZero, object);
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, object);

        /*------------------------------------------------查询营销活动周期维度汇总数据------------------------------------*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费减免活动周期统计表数据  规则为0的数据*/
        TMStatMfdPeriod tmStatMfdPeriod = selectMchntFeeDiscountPeriodStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, globalTxnDate, globalTxnDate);
        if (null == tmStatMfdPeriod) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费减免活动周期统计表数据查询结果为空!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdPeriod = new TMStatMfdPeriod();
            tmStatMfdPeriod.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            //获取不到周期统计数据，默认按照自然月度配置周期起始日期
            tmStatMfdPeriod.setPeriodStartDate(MompDateUtil.getSecondDay(Integer.parseInt(globalTxnDate.substring(0, 4)), Integer.parseInt(globalTxnDate.substring(4, 6))));
        } else {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}> 商户手续费减免活动周期统计表数据查询结束!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
        }

        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay2 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, batchDate);
            if (null == tmStatMfdDay2) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2 = new TMStatMfdDay();
                tmStatMfdDay2.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, tmStatMfdPeriod.getPeriodStartDate()) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，需要累加到周期统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到周期统计表!", batchDate);
                copyMchntFeeDiscountMchntStatData(tmStatMfdPeriod, tmStatMfdDay2);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }
        //将累计优惠手续费金额赋值——周期维度判断使用
        copyMchntFeeDiscountPeriodZeroStatData(tmStatMfdPeriod, tmStatMfdDay, ((McMchntFeeDiscountTxnData) object));

        return CommonConstant.ZERO;
    }

    /**
     * 手续费减免活动统计数据赋值
     *
     * @param tmStatMfd 手续费减免活动统计表
     * @param object    数据库操作对象
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountStatData(TMStatMfd tmStatMfd, Object object) {

        /* 营销活动累计-总预算累计消耗笔数 */
        ((McMchntFeeDiscountTxnData) object).setMcTotalQtyAcc(tmStatMfd.getTotalQtyAcc());
        /* 营销活动累计-总预算累计消耗金额 */
        ((McMchntFeeDiscountTxnData) object).setMcTotalAmtAcc(tmStatMfd.getTotalAmtAcc());
        /* 营销活动累计-总预算累计消耗笔数 */
        ((McMchntFeeDiscountTxnData) object).setMcTxnQtyAcc(tmStatMfd.getTxnQtyAcc());
        /* 营销活动累计-总预算累计消耗金额 */
        ((McMchntFeeDiscountTxnData) object).setMcTxnAmtAcc(tmStatMfd.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动周期统计数据赋值
     *
     * @param tmStatMfdPeriod 手续费减免活动周期统计表
     * @param object          数据库操作对象
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountPeriodStatData(TMStatMfdPeriod tmStatMfdPeriod, Object object) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        ((McMchntFeeDiscountTxnData) object).setPeriodTotalQtyAcc(tmStatMfdPeriod.getTotalQtyAcc());
        /* 营销活动单日累计-总预算累计消耗金额 */
        ((McMchntFeeDiscountTxnData) object).setPeriodTotalAmtAcc(tmStatMfdPeriod.getTotalAmtAcc());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        ((McMchntFeeDiscountTxnData) object).setPeriodTxnQtyAcc(tmStatMfdPeriod.getTxnQtyAcc());
        /* 营销活动单日累计-总预算累计消耗金额 */
        ((McMchntFeeDiscountTxnData) object).setPeriodTxnAmtAcc(tmStatMfdPeriod.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动单日统计数据赋值
     *
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @param object       操作对象
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountSingleDayStatData(TMStatMfdDay tmStatMfdDay, Object object) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        ((McMchntFeeDiscountTxnData) object).setDayTotalQtyAcc(tmStatMfdDay.getTotalQtyAcc());
        /* 营销活动单日累计-总预算累计消耗金额 */
        ((McMchntFeeDiscountTxnData) object).setDayTotalAmtAcc(tmStatMfdDay.getTotalAmtAcc());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        ((McMchntFeeDiscountTxnData) object).setDayTxnQtyAcc(tmStatMfdDay.getTxnQtyAcc());
        /* 营销活动单日累计-总预算累计消耗金额 */
        ((McMchntFeeDiscountTxnData) object).setDayTxnAmtAcc(tmStatMfdDay.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt 手续费减免活动商户统计表
     * @param object         操作对象
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountMchntStatData(TMStatMfdMchnt tmStatMfdMchnt, Object object) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        ((McMchntFeeDiscountTxnData) object).setMchntTotalQtyAcc(tmStatMfdMchnt.getTotalQtyAcc());
        /* 营销活动单日累计-总预算累计消耗金额 */
        ((McMchntFeeDiscountTxnData) object).setMchntTotalAmtAcc(tmStatMfdMchnt.getTotalAmtAcc());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        ((McMchntFeeDiscountTxnData) object).setMchntTxnQtyAcc(tmStatMfdMchnt.getTxnQtyAcc());
        /* 营销活动单日累计-总预算累计消耗金额 */
        ((McMchntFeeDiscountTxnData) object).setMchntTxnAmtAcc(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户统计数据(商户维度)赋值
     *
     * @param tmStatMfdMchnt 手续费减免活动商户统计表
     * @param object         操作对象
     * @author liujinan
     * @since 2020/9/24 11:23
     */
    private void copyMchntFeeDiscountMchntStat9999Data(TMStatMfdMchnt tmStatMfdMchnt, Object object) {

        /* 总预算累计优惠笔数 */
        ((McMchntFeeDiscountTxnData) object).setMchntTotalQtyAcc9999(tmStatMfdMchnt.getTotalQtyAcc());
        /* 总预算累计优惠金额 */
        ((McMchntFeeDiscountTxnData) object).setMchntTotalAmtAcc9999(tmStatMfdMchnt.getTotalAmtAcc());
        /* 总预算累计交易笔数 */
        ((McMchntFeeDiscountTxnData) object).setMchntTxnQtyAcc9999(tmStatMfdMchnt.getTxnQtyAcc());
        /* 总预算累计交易金额 */
        ((McMchntFeeDiscountTxnData) object).setMchntTxnAmtAcc9999(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户单日统计数据赋值
     *
     * @param tmStatMfdMchntDay 手续费减免活动商户单日统计表
     * @param object            操作对象
     * @author Jinan Liu
     * @since 2020/6/5 11:22
     */
    private void copyMchntFeeDiscountMchntDayStatData(TMStatMfdMchntDay tmStatMfdMchntDay, Object object) {

        /* 营销活动单日累计-累计优惠笔数 */
        ((McMchntFeeDiscountTxnData) object).setMchntDayTotalQtyAcc(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 营销活动单日累计-累计优惠金额 */
        ((McMchntFeeDiscountTxnData) object).setMchntDayTotalAmtAcc(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 营销活动单日累计-累计优惠笔数 */
        ((McMchntFeeDiscountTxnData) object).setMchntDayTxnQtyAcc(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 营销活动单日累计-累计优惠金额 */
        ((McMchntFeeDiscountTxnData) object).setMchntDayTxnAmtAcc(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 使用商户编号从内管商户基本信息表查询商户所属商圈编号
     *
     * @param globalInstId 法人机构号
     * @param mchntNo      商户编号
     * @return cc.rengu.igas.momp.common.entity.TBMchntBaseInfo 商户基本信息表T_B_MCHNT_BASE_INFO
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/5/28 13:06
     */
    private TBMchntBaseInfo selectMompMchntBaseInfoByPrimaryKey(String globalInstId, String mchntNo) throws Exception {

        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        return mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(globalInstId, mchntNo);
    }

    /**
     * 全局变量赋值
     *
     * @param comboPaymentRequest (合并)支付接口请求对象
     * @throws BizException 异常信息
     * @author Jinan Liu
     * @date 2020/7/21 16:37
     */
    private void messageValidation(ComboPaymentRequest comboPaymentRequest) throws BizException {

        if (StringUtil.isNullorEmpty(comboPaymentRequest.getHeader().getTransDate())) {
            rglog.error("交易日期必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalTxnDate = comboPaymentRequest.getHeader().getTransDate();
        }

        if (StringUtil.isNullorEmpty(comboPaymentRequest.getHeader().getTransTime())) {
            rglog.error("交易时间必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalTxnTime = comboPaymentRequest.getHeader().getTransTime();
        }

        if (StringUtil.isNullorEmpty(comboPaymentRequest.getHeader().getInstId())) {
            rglog.error("法人机构号必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalInstId = comboPaymentRequest.getHeader().getInstId();
        }

        if (StringUtil.isNullorEmpty(comboPaymentRequest.getHeader().getTraceNo())) {
            rglog.error("流水号必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalTraceNo = comboPaymentRequest.getHeader().getTraceNo();
        }

        globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        if (!StringUtil.isNullorEmpty(comboPaymentRequest.getMchntOrderId())) {
            globalOrderId = comboPaymentRequest.getMchntOrderId();
        } else {
            rglog.error("需要上送商户订单号!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        globalUserId = comboPaymentRequest.getUserId();
        if (!StringUtil.isNullorEmpty(globalUserId)) {
//            globalUserId = comboPaymentRequest.getUserId();
            boolean isJson = isJson(globalUserId);
            if (isJson) {
                userIdFlag = CommonConstant.THREE_COMMON_CONSTANT;
                rglog.info("上送userId为Json字符串,phoneNo<{}>,cardNo<{}>,wechatId<{}>,alipayId<{}>,coreComId<{}>,userIdFlag<{}>", phoneNo, cardNo, wechatId, alipayId, userIdFlag, coreComId);
            } else {
                userIdFlag = CommonConstant.TWO_COMMON_CONSTANT;
                rglog.info("上送userId<{}>", globalUserId);
            }
        } else {
            userIdFlag = CommonConstant.ONE_COMMON_CONSTANT;
            rglog.info("未上送userId");
        }
        if (!StringUtil.isNullorEmpty(comboPaymentRequest.getStageType()) && !StringUtil.isNullorEmpty(comboPaymentRequest.getStageNum())
                && !StringUtil.isNullorEmpty(comboPaymentRequest.getStageCode())) {
            stageType = comboPaymentRequest.getStageType();
            stageNum = comboPaymentRequest.getStageNum();
            stageCode = comboPaymentRequest.getStageCode();
            rglog.error("该交易为分期业务,分期类型<{}>，分期期数<{}>,分期code<{}>!", stageType, stageNum, stageCode);
        }

        // 检查上传字段 不能为负数
        /* 交易金额 */
        if (!StringUtil.isNullorEmpty(comboPaymentRequest.getTransAmt()) && new BigDecimal(comboPaymentRequest.getTransAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }

        tmStat2CDayList = new ArrayList<>();
        tmStat2CMchntDayList = new ArrayList<>();
        tbMchntBaseInfoList = new ArrayList<>();
        tmTxnOrderDetList = new ArrayList<>();
        tmStatMfdDayList = new ArrayList<>();
        tmStatMfdMchntDayList = new ArrayList<>();
        statMfdDayList = new ArrayList<>();
        paymentOrderMoneyOffInfoBeanList = comboPaymentRequest.getMoneyOffInfoBeanList();
        paymentOrderDetailBeanList = comboPaymentRequest.getOrderDetailList();
        if (null == paymentOrderDetailBeanList || paymentOrderDetailBeanList.isEmpty()) {
            rglog.error("需上送订单明细!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            /* 应答数据初始化 */
            for (PaymentOrderDetailBean paymentOrderDetailBean : paymentOrderDetailBeanList) {
                /*满减实际支付金额*/
                paymentOrderDetailBean.setMoneyOffTxnAmt(paymentOrderDetailBean.getMoneyOffTxnAmt());
                /* 满减补贴金额*/
                paymentOrderDetailBean.setMoneyOffSubsidyTotal(CommonConstant.ZERO_AMOUNT);
                /*满减机构补贴金额*/
                paymentOrderDetailBean.setMoneyOffSubsidyBank(CommonConstant.ZERO_AMOUNT);
                /*满减商户补贴金额*/
                paymentOrderDetailBean.setMoneyOffSubsidyMchnt(CommonConstant.ZERO_AMOUNT);
                /*卡券抵扣补贴金额*/
                paymentOrderDetailBean.setCouponTotalSubsidy(CommonConstant.ZERO_AMOUNT);
                /*卡券机构补贴金额*/
                paymentOrderDetailBean.setCouponBankSubsidy(CommonConstant.ZERO_AMOUNT);
                /*卡券商户补贴金额*/
                paymentOrderDetailBean.setCouponMchntSubsidy(CommonConstant.ZERO_AMOUNT);
                /*手续费优惠金额*/
                paymentOrderDetailBean.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT);
                /*实收手续费金额*/
                paymentOrderDetailBean.setMchntFeeActual(paymentOrderDetailBean.getMchntFeeReceivable());
            }
        }

        globalDiscountFlag = false;
        procNormalStatus = false;


        tmTxnOrder = new TMTxnOrder();
        tmTxnOrder.setInstId(globalInstId);
        tmTxnOrder.setTxnDate(globalTxnDate);
        tmTxnOrder.setTxnTime(globalTxnTime);
        tmTxnOrder.setTxnNum(comboPaymentRequest.getHeader().getTxnNum());
        tmTxnOrder.setBizType(comboPaymentRequest.getHeader().getBizType());
        tmTxnOrder.setBizProdCode(comboPaymentRequest.getBizProdCode());
        tmTxnOrder.setMsgSrcId(comboPaymentRequest.getHeader().getSrcSysId());
        tmTxnOrder.setFrontSeqNum(globalTraceNo);
        tmTxnOrder.setOrderId(globalOrderId);
//        tmTxnOrder.setMchntNo(comboPaymentRequest.getMchntOrderId());
        tmTxnOrder.setUserId(globalUserId);
        tmTxnOrder.setOrderAmt(comboPaymentRequest.getTransAmt());
        tmTxnOrder.setTxnAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setBankSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrder.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        tmTxnOrder.setOrderRemark("{}");
        tmTxnOrder.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrder.setCreateTime(globalTimeStamp);
    }

    /**
     * 数据库统一操作
     * 返回0表示成功
     * 返回-1表示失败
     *
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/10 00:13
     */
    private int databaseOperation() throws Exception {

        int returnCode;

        /* 卡券核销 */
        if (tmCouponInfo != null) {

            rglog.debug("更新法人机构<{}>的卡券营销活动<{}>的卡券<{}>信息", tmCouponInfo.getInstId(), tmCouponInfo.getMcNo(), tmCouponInfo.getCouponNo());

            tmCouponInfo.setCouponStatus(CouponStatusEnum.REDEEMED.getCouponStatusCode());
            tmCouponInfo.setOrderId(globalOrderId);
            tmCouponInfo.setRedeemTime(globalTxnDate + globalTxnTime);
            tmCouponInfo.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmCouponInfo.setUpdateTime(globalTimeStamp);

            CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
            returnCode = couponInfoMapper.redeemSingleCoupon(tmCouponInfo);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("法人机构<{}>的卡券营销活动<{}>的卡券<{}>核销失败! RETURN_CODE=<{}>",
                        globalInstId, tmCouponInfo.getMcNo(), tmCouponInfo.getCouponNo(), returnCode);
                return CommonConstant.PROCESS_FAILED;
            }
        }

        /* 更新对客类额度 */
        if (!tmStat2CDayList.isEmpty()) {

            rglog.info("对客类营销活动单日统计表待处理数据记录数<{}>", tmStat2CDayList.size());

            TMStat2CDayMapper tmStat2CDayMapper = new TMStat2CDayMapperImpl();
            rglog.info("循环插入对客类营销活动单日统计表,先更新再插入");
            for (TMStat2CDay tmStat2CDay : tmStat2CDayList) {
                /* 先更新数据,更新失败再插入数据 */
                returnCode = tmStat2CDayMapper.updateToClientMcDayStatistics(tmStat2CDay);
                if (Database.DBS_NOT_FOUND == returnCode) {
                    /* 插入数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                    returnCode = tmStat2CDayMapper.insertSingleToClientMcDayStatistics(tmStat2CDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        /* 更新失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    }
                    rglog.info("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex());
                } else if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex());
                }
                //判断规则不为0
                rglog.info("判断规则顺序号是否为0,顺序号<{}>", tmStat2CDay.getRuleIndex());
                if (!tmStat2CDay.getRuleIndex().equals(CommonConstant.ZERO_COMMON_CONSTANT)) {
                    //查询手续费减免活动单日统计表数据，限制规则为具体值
                    rglog.info("查询对客类营销活动单日统计表数据，限制规则顺序号为0");
                    TMStat2CDay oldTMStat2CDay = new TMStat2CDay();
                    oldTMStat2CDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                    oldTMStat2CDay.setInstId(tmStat2CDay.getInstId());
                    oldTMStat2CDay.setMcNo(tmStat2CDay.getMcNo());
                    oldTMStat2CDay.setTxnDate(tmStat2CDay.getTxnDate());
                    oldTMStat2CDay = tmStat2CDayMapper.selectToClientMcDayStatistics(oldTMStat2CDay);
                    if (null == oldTMStat2CDay) {
                        rglog.info("规则顺序号为0的对客类营销活动单日统计表数据为空,需插入一条顺序号为0的新数据");
                        tmStat2CDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                        returnCode = tmStat2CDayMapper.insertSingleToClientMcDayStatistics(tmStat2CDay);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                            /* 更新失败 */
                            rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                            return CommonConstant.PROCESS_FAILED;
                        }
                    } else {
                        rglog.info("更新规则顺序号为0的对客类营销活动单日统计表数据");
                        tmStat2CDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                        returnCode = tmStat2CDayMapper.updateToClientMcDayStatistics(tmStat2CDay);
                        if (Database.DBS_SUCCESS != returnCode) {
                            rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                            return CommonConstant.PROCESS_FAILED;
                        }
                    }
                }
            }
        }

        if (!tmStat2CMchntDayList.isEmpty()) {

            rglog.info("对客类营销活动商户单日统计表待处理数据记录数<{}>", tmStat2CMchntDayList.size());

            TMStat2CMchntDayMapper tmStat2CMchntDayMapper = new TMStat2CMchntDayMapperImpl();
            for (TMStat2CMchntDay tmStat2CMchntDay : tmStat2CMchntDayList) {

                /* 先更新数据,更新失败再插入数据 */
                returnCode = tmStat2CMchntDayMapper.updateToClientMcMchntDayStatistics(tmStat2CMchntDay);
                if (Database.DBS_NOT_FOUND == returnCode) {
                    /* 插入数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo(), returnCode);
                    returnCode = tmStat2CMchntDayMapper.insertSingleToClientMcMchntDayStatistics(tmStat2CMchntDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        /* 更新失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    }
                    rglog.info("插入法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据成功", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo());
                } else if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("更新法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据成功", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo());
                }
            }
        }

        /* 更新手续费优惠类额度 */
        if (!tmStatMfdDayList.isEmpty()) {

            rglog.info("商户手续费优惠类营销活动单日统计表待处理数据记录数<{}>", tmStatMfdDayList.size());

            /* 手续费减免活动单日统计表 */
            TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
            //循环插入手续费活动单日统计表
            rglog.info("循环插入手续费活动单日统计表,先更新再插入");
            for (TMStatMfdDay tmStatMfdDay : tmStatMfdDayList) {
                /* 先更新数据,更新失败再插入数据 */
                returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
                if (Database.DBS_NOT_FOUND == returnCode) {
                    /* 插入数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    returnCode = tmStatMfdDayMapper.insertMchntFeeDiscountDayStatistics(tmStatMfdDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        /* 更新失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    }
                    rglog.info("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                } else if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                }
                //判断规则不为0
                rglog.info("判断规则顺序号是否为0,顺序号<{}>", tmStatMfdDay.getRuleIndex());
                if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay.getRuleIndex())) {
                    //查询手续费减免活动单日统计表数据，限制规则为具体值
                    rglog.info("查询手续费减免活动单日统计表数据，限制规则顺序号为0");
                    TMStatMfdDay oldTmStatMfdDayRuleIndexIsZero = tmStatMfdDayMapper.selectMchntFeeDiscountDayStatisticsByPK(tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), CommonConstant.ZERO_COMMON_CONSTANT, tmStatMfdDay.getTxnDate());
                    if (null == oldTmStatMfdDayRuleIndexIsZero) {
                        rglog.info("规则顺序号为0的手续费减免活动单日统计表数据为空,需插入一条顺序号为0的新数据");
                        tmStatMfdDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                        returnCode = tmStatMfdDayMapper.insertMchntFeeDiscountDayStatistics(tmStatMfdDay);
                        if (Database.DBS_SUCCESS != returnCode) {
                            rglog.error("营销活动<{}> 规则<{}> 插入手续费减免活动单日统计表失败!", tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                            throw new BizException(RespCodeEnum.FAILED_TO_INSERT_STATISTICAL_INFO.getRespCode(), RespCodeEnum.FAILED_TO_INSERT_STATISTICAL_INFO.getRespDesc());
                        }
                    } else {
                        rglog.info("更新规则顺序号为0的手续费减免活动单日统计表数据");
                        tmStatMfdDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                        returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
                        if (Database.DBS_SUCCESS != returnCode) {
                            rglog.error("营销活动<{}> 规则<{}> 更新手续费减免活动单日统计表失败!", tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                            throw new BizException(RespCodeEnum.FAILED_TO_INSERT_STATISTICAL_INFO.getRespCode(), RespCodeEnum.FAILED_TO_INSERT_STATISTICAL_INFO.getRespDesc());
                        }
                    }
                }
            }
        }

        if (!tmStatMfdMchntDayList.isEmpty()) {

            rglog.info("商户手续费优惠类营销活动商户单日统计表待处理数据记录数<{}>", tmStatMfdMchntDayList.size());

            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
            rglog.info("循环插入商户手续费优惠类营销活动商户单日统计表,先更新再插入");
            for (TMStatMfdMchntDay tmStatMfdMchntDay : tmStatMfdMchntDayList) {

                /* 先更新数据,更新失败再插入数据 */
                returnCode = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                if (Database.DBS_NOT_FOUND == returnCode) {
                    /* 插入数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    returnCode = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        /* 更新失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    }
                    rglog.info("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex());
                } else if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex());
                }
                //判断规则不为0
                rglog.info("判断规则顺序号是否为0,顺序号<{}>", tmStatMfdMchntDay.getRuleIndex());
                if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay.getRuleIndex())) {
                    rglog.info("查询商户手续费优惠类营销活动商户单日统计表数据，限制规则顺序号为0");
                    TMStatMfdMchntDay oldTmStatMfdMchntDay = tmStatMfdMchntDayMapper.selectMchntFeeDiscountMchntDayStatisticsByPK(tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), CommonConstant.ZERO_COMMON_CONSTANT, tmStatMfdMchntDay.getMchntNo(), tmStatMfdMchntDay.getTxnDate());
                    if (null == oldTmStatMfdMchntDay) {
                        rglog.info("规则顺序号为0的商户手续费优惠类营销活动商户单日统计表数据为空,需插入一条顺序号为0的新数据");
                        tmStatMfdMchntDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                        returnCode = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                            /* 更新失败 */
                            rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                            return CommonConstant.PROCESS_FAILED;
                        }
                    } else {
                        rglog.info("更新规则顺序号为0的商户手续费优惠类营销活动商户单日统计表数据");
                        tmStatMfdMchntDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                        returnCode = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                            /* 更新失败 */
                            rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                            return CommonConstant.PROCESS_FAILED;
                        }
                    }
                }
            }
        }

        //当前订单是否只有手续费金额优惠而没有实际手续费优惠，用于是否对账的判断
        boolean isOnlyMchntFeeDiscountAmt = false;
        //手续费优惠总金额
        BigDecimal totalMchntFeeSubsidy = BigDecimal.ZERO;
        /* 登记订单明细 */
        if (!tmTxnOrderDetList.isEmpty()) {

            rglog.info("订单明细表待处理数据记录数<{}>", tmTxnOrderDetList.size());

            TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
            for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetList) {
                //若果订单明细不是手续费优惠的，则本订单肯定有优惠，需要参与对账
                if (!McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode().equals(tmTxnOrderDet.getMcType())) {
                    isOnlyMchntFeeDiscountAmt = true;
                } else {
                    //如果本明细是手续费优惠的，则手续费优惠金额累加，最后判断累加值是否有优惠，如果有则参与对账，如果没有则不参与对账
                    totalMchntFeeSubsidy = totalMchntFeeSubsidy.add(new BigDecimal(tmTxnOrderDet.getSubsidy()).abs());
                }

                /* 插入数据 */
                returnCode = tmTxnOrderDetMapper.insertSingleRecordIntoTMTxnOrderDet(tmTxnOrderDet);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    /* 更新失败 */
                    rglog.error("插入法人机构<{}>的营销活动<{}>的商户<{}>的订单明细数据失败! RETURN_CODE=<{}>", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getMcNo(), tmTxnOrderDet.getMchntNo(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                }
                rglog.info("插入法人机构<{}>的营销活动<{}>的商户<{}>的订单明细数据成功", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getMcNo(), tmTxnOrderDet.getMchntNo());
            }

            /* 存在至少一个订单明细时插入正常订单流水 */
            if (null != tmTxnOrder) {

                if (isOnlyMchntFeeDiscountAmt) {
                    //只要有非手续费的营销，肯定需要对账，则为true，
                    tmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_TRUE_CHECK_FLAG_TRUE);
                } else {
                    //订单明细均为手续费优惠的明细，则判断优惠金额，如果有手续费优惠，则需要对账，没有则不需要对账
                    if (totalMchntFeeSubsidy.compareTo(BigDecimal.ZERO) == 0) {
                        tmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_TRUE_CHECK_FLAG_FALSE);
                    } else {
                        tmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_TRUE_CHECK_FLAG_TRUE);
                    }
                }

                /* 登记订单流水 */
                TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
                returnCode = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(tmTxnOrder);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    /* 更新失败 */
                    rglog.error("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据失败! RETURN_CODE=<{}>", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                }
                rglog.info("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据成功!", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
            }
        } else {

            /* 无订单明细时插入处理成功但无优惠的订单流水 */
            if (null != tmTxnOrder) {

                tmTxnOrder.setTxnAmt(tmTxnOrder.getOrderAmt());
                tmTxnOrder.setSubsidyAmt(CommonConstant.ZERO_AMOUNT);
                tmTxnOrder.setBankSubsidyAmt(CommonConstant.ZERO_AMOUNT);
                tmTxnOrder.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);
                tmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_FALSE_CHECK_FLAG_FALSE);

                /* 登记订单流水 */
                TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
                returnCode = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(tmTxnOrder);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    /* 更新失败 */
                    rglog.error("插入法人机构<{}>的流水号<{}>的订单号<{}>的无优惠订单数据失败! RETURN_CODE=<{}>", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                }
                rglog.info("插入法人机构<{}>的流水号<{}>的订单号<{}>的无优惠订单数据成功!", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 检查商户是否可作为手续费优惠活动的新增商户
     * 返回true-成功
     * 返回false-失败，不可作为新商户享受免手续费优惠
     *
     * @param mchntNo                  商户号
     * @param tmMcMchntFeeDiscountInfo 商户手续费减免类营销活动信息表
     * @param mchntExpandDate          商户入驻日期
     * @return boolean 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/7/28 15:40
     */
    private boolean checkNewMchntAvailability(String mchntNo, TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo, String mchntExpandDate, Boolean notDistinguishMiddleOfMonth) throws Exception {

        String mcNo = tmMcMchntFeeDiscountInfo.getMcNo();

        int monthPeriod = Integer.parseInt(tmMcMchntFeeDiscountInfo.getNewMchntPeriod());
        String periodEndDate;
        //不区分15号之前之后时
        if (notDistinguishMiddleOfMonth) {
            periodEndDate = MompDateUtil.getFutureMonFirstDay(mchntExpandDate, monthPeriod);
        } else {
            periodEndDate = MompDateUtil.getFutureMonAddOneFirstDay(mchntExpandDate, monthPeriod);
        }
        String mcEndDate = tmMcMchntFeeDiscountInfo.getMcEndDate();
//        String periodEndDate = MompDateUtil.getLastDay(year, month);
        String postponeFlag = tmMcMchntFeeDiscountInfo.getPostponeFlag();

        //如果免手续费到期时间在活动结束时间之前
        if (MompDateUtil.checkDateRange(periodEndDate, mcEndDate)) {
            tmMcMchntFeeDiscountInfo.setRemark1(periodEndDate);
        } else {
            //判断是否顺延，如果顺延，免费周期为顺延后的到期时间，保存到remark1中,后续使用此字段判断免费周期最长的
            if (CommonConstant.NEW_MCHNT_DISCOUNT_PROLONG.equals(postponeFlag)) {
                tmMcMchntFeeDiscountInfo.setRemark1(periodEndDate);
            } else {
                tmMcMchntFeeDiscountInfo.setRemark1(mcEndDate);
            }
        }

        if (MompDateUtil.checkDateRange(globalTxnDate, mcEndDate) && MompDateUtil.checkDateRange(globalTxnDate, periodEndDate)) {
            /* 当前交易日期同时在活动结束日期和最后的新商户统计周期内,可以优惠 */
            rglog.info("法人机构<{}>的商户手续费优惠活动<{}>可以对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
            return true;

        } else if (MompDateUtil.checkDateRange(globalTxnDate, periodEndDate)) {

            /* 当前交易日期在活动结束日期外,但在新商户统计周期内,需进一步判断 */
            if (CommonConstant.NEW_MCHNT_DISCOUNT_END.equals(postponeFlag)) {
                /* 活动结束后周期不自动顺延,即活动结束后就没有新商户免手续费的优惠 */
                rglog.error("法人机构<{}>的商户手续费优惠活动<{}>不支持新增商户周期顺延!该营销活动不可对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
                return false;

            } else if (CommonConstant.NEW_MCHNT_DISCOUNT_PROLONG.equals(postponeFlag)) {
                /* 商户手续费优惠营销活动新入驻商户活动结束后周期自动顺延 */
                rglog.info("法人机构<{}>的商户手续费优惠活动<{}>支持新增商户周期顺延!该营销活动可以对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
                return true;

            } else {
                rglog.error("法人机构<{}>的商户手续费优惠活动<{}>的新增商户周期顺延标志数据异常!该营销活动不可对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
                return false;
            }
        } else {
            rglog.error("商户<{}>在当前日期<{}>已不满足参加法人机构<{}>的商户手续费优惠活动<{}>并免手续费的条件!", mchntNo, globalTxnDate, globalInstId, mcNo);
            return false;
        }
    }

    /**
     * 新增商户手续费减免达标数据统计表数据生成
     *
     * @param mchntNo                  商户号
     * @param tmMcMchntFeeDiscountInfo 商户手续费减免类营销活动信息表
     * @param mchntExpandDate          商户入驻日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdCriteria 手续费减免达标数据统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/7/7 18:05
     */
    private TMStatMfdCriteria generateNewMchntCriteriaData(String mchntNo, TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo, String mchntExpandDate, Boolean notDistinguishMiddleOfMonth) throws Exception {

        String mcNo = tmMcMchntFeeDiscountInfo.getMcNo();

        TMStatMfdCriteria value = null;
        List<TMStatMfdCriteria> tmStatMfdCriteriaList = new ArrayList<>();

        int monthNum = Integer.parseInt(tmMcMchntFeeDiscountInfo.getNewMchntPeriod());

        int year = Integer.parseInt(mchntExpandDate.substring(0, 4));
        int month = Integer.parseInt(mchntExpandDate.substring(4, 6));
        //商户入驻日，用于判断是1号还是15号之后
        int day = Integer.parseInt(mchntExpandDate.substring(6));

        //如果配置了不区分15号时
        if (notDistinguishMiddleOfMonth) {
            rglog.info("营销活动<{}> 商户<{}> 机构<{}>配置了新商户不区分15号之前之后入驻,继续生成达标统计表数据", mcNo, mchntNo, globalInstId);
        } else {
            //如果没有配置（为空）时或者配置的为区分15号时，则进行区分15号之前之后的处理
            rglog.info("营销活动<{}> 商户<{}> 机构下的新商户区分15号之前之后入驻,继续生成达标统计表数据", mcNo, mchntNo);
            if (CommonConstant.MIDDLE_OF_MONTH < day) {
                //如果日期大于15号，则免手续费周期加1
                monthNum++;
            }
        }

        String startDate = mchntExpandDate;
        //活动开始日期
        String mcStartDate = tmMcMchntFeeDiscountInfo.getMcStartDate();
        String mcEndDate = tmMcMchntFeeDiscountInfo.getMcEndDate();
        String postponeFlag = tmMcMchntFeeDiscountInfo.getPostponeFlag();

        for (int i = 0; i < monthNum; i++) {

            String periodStartDate = MompDateUtil.getSecondDay(year, month);
            if (i == 0) {
                //第一个周期，取入驻月份的第一天
                periodStartDate = MompDateUtil.getFirstDay(year, month);
                //第一个周期 判断活动开始日期是否小于第一个周期开始日期
                int code = DateUtil.compareDate(mcStartDate, periodStartDate);
                if (code > 0) {
                    periodStartDate = mcStartDate;
                }
            }
            String periodEndDate = MompDateUtil.getNextMonthFirstDay(year, month);

            if (CommonConstant.NEW_MCHNT_DISCOUNT_END.equals(postponeFlag)) {
                /* 如果支持新增商户的营销活动在活动结束后不自动顺延新增商户免手续费的周期,需要判断生成的新商户统计周期是否在活动起止日期内 */
                if (MompDateUtil.checkDateRange(periodEndDate, mcEndDate)) {
                    /* 如果当前生成统计周期在起止日期内,流程正常流转 */
                    //最后一个周期到本月的最后一天 不是下月的1号  --20210305杨斌提出改动，新商户达标统计表最后一个周期不是月底最后一天，应该和其他的一样，为下月的1号
//                    if (i == monthNum-1){
//                        periodEndDate =MompDateUtil.getMonthTheLastDay(year,month);
//                    }
                } else {
                    /* 如果当前生成统计周期不在起止日期内,需要判断当前周期起始日期是否在营销活动起止日期内 */
                    if (MompDateUtil.checkDateRange(periodStartDate, mcEndDate)) {
                        /* 当前周期起始日期在营销活动起止日期内,当前统计周期开始日期不变,结束日期变为营销活动结束日期 */
                        periodEndDate = mcEndDate;
                    } else {
                        break;
                    }
                }
            } else if (CommonConstant.NEW_MCHNT_DISCOUNT_PROLONG.equals(postponeFlag)) {
                /* 支持新增商户的营销活动在活动结束后自动顺延新增商户免手续费的周期，流程正常流转 */
                //最后一个周期到本月的最后一天 不是下月的1号  --20210305杨斌提出改动，新商户达标统计表最后一个周期不是月底最后一天，应该和其他的一样，为下月的1号
//                if (i == monthNum-1){
//                    periodEndDate =MompDateUtil.getMonthTheLastDay(year,month);
//                }
            } else {
                /* 状态异常 */
                rglog.error("法人机构<{}>的商户手续费优惠活动<{}>的新增商户周期顺延标志数据异常!该营销活动不可对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
                return null;
            }

            TMStatMfdCriteria tmStatMfdCriteria = new TMStatMfdCriteria();
            tmStatMfdCriteria.setInstId(globalInstId);
            tmStatMfdCriteria.setMcNo(tmMcMchntFeeDiscountInfo.getMcNo());
            tmStatMfdCriteria.setMchntNo(mchntNo);
            tmStatMfdCriteria.setPeriodStartDate(periodStartDate);
            tmStatMfdCriteria.setPeriodEndDate(periodEndDate);
            tmStatMfdCriteria.setRecIndex(Integer.toString(i + 1));
            tmStatMfdCriteria.setBeforeFlag(tmMcMchntFeeDiscountInfo.getBeforeFlag());
            tmStatMfdCriteria.setAfterFlag(tmMcMchntFeeDiscountInfo.getAfterFlag());
            tmStatMfdCriteria.setNewMchntFlag(CommonConstant.MCHNT_NEW_FLAG);
            tmStatMfdCriteria.setNewMchntDate(mchntExpandDate);
            tmStatMfdCriteria.setNewMchntStartDate(startDate);
            tmStatMfdCriteria.setNewMchntEndDate(tmMcMchntFeeDiscountInfo.getRemark1());
            tmStatMfdCriteria.setExitDiscountStatus(CommonConstant.MC_NOT_EXIT_FLAG);
            tmStatMfdCriteria.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdCriteria.setCreateTime(globalTimeStamp);
            tmStatMfdCriteria.setMrctDisUpLmtVal(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());

            if (CommonConstant.ZERO == MompDateUtil.checkDateRange(globalTxnDate, periodStartDate, periodEndDate)) {
                value = tmStatMfdCriteria;
            }

            tmStatMfdCriteriaList.add(tmStatMfdCriteria);

            if (month >= 12) {
                month = 1;
                year++;
            } else {
                month++;
            }
        }

        /* 插入数据 */
        int returnCode = insertMfdCriteriaData(tmStatMfdCriteriaList);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("将新增商户续费减免达标数据统计表数据插入数据库操作失败! RETURN_CODE=<{}>", returnCode);
            return null;
        } else {
            return value;
        }
    }

    /**
     * 插入新增商户续费减免达标数据统计表数据
     *
     * @param tmStatMfdCriteriaList 手续费减免达标数据统计表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020-07-07 23:02
     */
    private int insertMfdCriteriaData(List<TMStatMfdCriteria> tmStatMfdCriteriaList) throws Exception {

        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        return tmStatMfdCriteriaMapper.insertNewMchntCriteriaData(tmStatMfdCriteriaList);
    }

    /**
     * 确保任何情况下订单流水表都有记录
     *
     * @param xmlTreeUtil 内部XML树
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020-08-05 18:22
     */
    private void onlyRecordTxnOrderInfo(XmlTreeUtil xmlTreeUtil) throws Exception {

        /* 报文检查时已new对象,直接使用即可 */
        if (null == tmTxnOrder) {
            rglog.error("订单流水表数据库操作实体类为空,不可记录订单流水信息!");
            return;
        } else {

            if (procNormalStatus) {
                /* 如果交易状态是正常 */
                tmTxnOrder.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
                rglog.info("法人机构<{}>的流水号<{}>的订单号<{}>的订单处理成功!", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());

            } else {
                /* 如果交易状态是异常 */
                tmTxnOrder.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_FAILED.getBizStatusCode());
                rglog.info("法人机构<{}>的流水号<{}>的订单号<{}>的订单处理失败!", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());

            }

            /* 如果无优惠 */
            tmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_FALSE_CHECK_FLAG_FALSE);
            rglog.info("法人机构<{}>的流水号<{}>的订单号<{}>的订单无优惠!", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());


            tmTxnOrder.setTxnAmt(tmTxnOrder.getOrderAmt());
            tmTxnOrder.setSubsidyAmt(CommonConstant.ZERO_AMOUNT);
            tmTxnOrder.setBankSubsidyAmt(CommonConstant.ZERO_AMOUNT);
            tmTxnOrder.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);

            /* 开启数据库事务 */
            String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
            String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
            if (null != corporation && !corporation.isEmpty()) {
                String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
                dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
            }
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            dbsUtil.dbsBeginTransaction();

            TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
            int returnCode = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(tmTxnOrder);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                /* 更新失败 */
                rglog.error("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据失败! RETURN_CODE=<{}>", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId(), returnCode);
                dbsUtil.dbsEndTransaction(false);
            } else {
                rglog.info("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据成功!", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
                dbsUtil.dbsEndTransaction(true);
            }
        }
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param mchntNo
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt
     * @throws Exception
     * @author liujinan
     * @date 2020/9/15
     */
    private TMStatMfdMchnt selectNowPeriodDateTMStatMfdMchnt(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 手续费减免活动商户单日统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfdMchntDay 手续费减免活动商户单日统计表
     * @author liujinan
     * @since 2020/9/25 11:22
     */
    private void copyMchntFeeDiscountMchntDayZeroStatData(TMStatMfdMchntDay tmStatMfdMchntDay, Object object) {

        /* 手续费减免活动商户单日统计数据-累计优惠笔数 */
        ((McMchntFeeDiscountTxnData) object).setMchntDayTotalQtyAccZero(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计优惠金额 */
        ((McMchntFeeDiscountTxnData) object).setMchntDayTotalAmtAccZero(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 手续费减免活动商户单日统计数据-累计交易笔数 */
        ((McMchntFeeDiscountTxnData) object).setMchntDayTxnQtyAccZero(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计交易金额 */
        ((McMchntFeeDiscountTxnData) object).setMchntDayTxnAmtAccZero(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author JL Pang
     * @since 2020/10/18 11:22
     */
    private void copyMchntFeeDiscountZeroStatData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay, Object object) {

        BigDecimal thisOrderTotalAmtAcc = BigDecimal.ZERO;
        List<TMStatMfdDay> statMfdThisOrderList = statMfdDayList.stream().filter(item -> item.getInstId().equals(((McMchntFeeDiscountTxnData) object).getInstId()) && item.getMcNo().equals(((McMchntFeeDiscountTxnData) object).getMcNo())).collect(Collectors.toList());
        if (statMfdThisOrderList.size() > 0) {
            //本笔流水中交易额,包含本笔明细中的
            TMStatMfdDay statMfdThisOrder = statMfdThisOrderList.get(0);
            thisOrderTotalAmtAcc = new BigDecimal(statMfdThisOrder.getTotalAmtAcc());
        }

        /* 手续费减免活动统计数据-总预算消耗金额 加本订单中参加相同活动的商户消耗预算，不加本明细手续费*/
        ((McMchntFeeDiscountTxnData) object).setMcTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).
                add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).
                add(thisOrderTotalAmtAcc).
                subtract(new BigDecimal(((McMchntFeeDiscountTxnData) object).getMchntFeeDiscount())).toString());
    }

    /**
     * 计算新增商户优惠的手续费
     *
     * @return CommonConstant.ZERO:成功，流程继续  1:本次结束，继续下一次
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/10/16
     */
    private int getNewMchntFeeDiscount(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {

        /* 获取交易额度上限 */
        rglog.info("机构<{}> 商户<{}> 营销活动<{}> 获取各维度统计数据开始...!", globalInstId, mcMchntFeeDiscountTxnData.getMchntNo(), mcMchntFeeDiscountTxnData.getMcNo());
        int returnCode = fetchNewMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTxnData);
        if (CommonConstant.ONE == returnCode) {
            rglog.info("获取机构<{}>的营销活动<{}>各维度限额和额度失败,本营销活动不予优惠!", globalInstId, mcMchntFeeDiscountTxnData.getMcNo());
            return CommonConstant.ONE;
        }

        /* 判断交易额度上限 */
        rglog.info("机构<{}> 商户<{}> 营销活动<{}> 判断交易额度限制开始...!", globalInstId, mcMchntFeeDiscountTxnData.getMchntNo(), mcMchntFeeDiscountTxnData.getMcNo());
        returnCode = checkNewMchntFeeDiscountLimits(mcMchntFeeDiscountTxnData);
        if (CommonConstant.ONE == returnCode) {
            rglog.info("机构<{}>的营销活动<{}>判断各维度限额和额度未通过,本营销活动不予优惠!", globalInstId, mcMchntFeeDiscountTxnData.getMcNo());
            return CommonConstant.ONE;
        }

        rglog.info("通过限额检查后计算出的机构<{}>的商户的<{}>的商户手续费优惠营销活动<{}>的减免金额<{}>,实收手续费<{}>", globalInstId, mcMchntFeeDiscountTxnData.getMchntNo(),
                mcMchntFeeDiscountTxnData.getMcNo(), mcMchntFeeDiscountTxnData.getMchntFeeDiscount(), mcMchntFeeDiscountTxnData.getMchntFeeActual());

        return CommonConstant.ZERO;
    }

    /**
     * 商户手续费优惠类营销活动交易限额处理
     *
     * @param mcMchntFeeDiscountTxnData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/18 17:36
     */
    private int checkNewMchntFeeDiscountLimits(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {

        String instId = mcMchntFeeDiscountTxnData.getInstId();
        String mcNo = mcMchntFeeDiscountTxnData.getMcNo();
        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();
        String newmrctFreeLmtTyp = mcMchntFeeDiscountTxnData.getNewmrctFreeLmtTyp();

        //本笔手续费优惠订单金额
        BigDecimal orderAmt = new BigDecimal(mcMchntFeeDiscountTxnData.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户统计-累计交易金额
        BigDecimal txnAmtAcc = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntTxnAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户单日统计数据 具体规则-累计交易金额
        BigDecimal txnAmtAccDay = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntDayTxnAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户统计-累计优惠手续费金额
        BigDecimal mchntTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户单日统计数据 具体规则-累计优惠手续费金额
        BigDecimal mchntTotalAmtAccDay = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntDayTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        //本笔应收手续费
        BigDecimal mchntFeeReceivable = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
        //本笔优惠手续费 新商户手续费全免，优惠=应收
        BigDecimal mchntFeeDiscount = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeDiscount());


        BigDecimal discountLimit;
        /* 判断新商户优惠上限是否超限 */
        if (null != mcMchntFeeDiscountTxnData.getMrctDisUpLmtVal() && !"".equals(mcMchntFeeDiscountTxnData.getMrctDisUpLmtVal())) {
            discountLimit = new BigDecimal(mcMchntFeeDiscountTxnData.getMrctDisUpLmtVal()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        } else {
            discountLimit = new BigDecimal(mcMchntFeeDiscountTxnData.getNewMchntAmountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        }

        //如果新商户上限为免交易金额，为空时默认为免交易金额
        if (null == newmrctFreeLmtTyp || CommonConstant.ZERO_COMMON_CONSTANT.equals(newmrctFreeLmtTyp)) {
            //本笔交易金额 + 周期统计累计优惠交易金额 + 单日统计累计优惠交易金额
            BigDecimal totalDiscount = orderAmt.add(txnAmtAcc).add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("新商户周期内优惠上限<{}>,加本笔交易总优惠金额<{}>", discountLimit, totalDiscount);

            if (CommonConstant.ZERO <= discountLimit.compareTo(totalDiscount)) {
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>规则<{}>加本次已优惠<{}>优惠上限<{}>校验通过，未超规则限额!流程继续！", instId, mcNo, mcMchntFeeDiscountTxnData.getRuleIndex(), totalDiscount, discountLimit);
            } else {
                BigDecimal historyTotalDiscount = txnAmtAcc.add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                if (CommonConstant.ZERO < discountLimit.compareTo(historyTotalDiscount)) {
                    BigDecimal remainderDiscountAmt = discountLimit.subtract(historyTotalDiscount).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>规则<{}>不加本次已优惠<{}>优惠上限<{}> 有剩余可优惠额度<{}>，开始重新计算手续费！", instId, mcNo, mcMchntFeeDiscountTxnData.getRuleIndex(), historyTotalDiscount, discountLimit, remainderDiscountAmt);
                    //重新计算手续费
                    boolean recalculateMchntFee = recalculateMchntFee(mcMchntFeeDiscountTxnData, orderAmt, remainderDiscountAmt, CommonConstant.ONE_COMMON_CONSTANT);
                    if (recalculateMchntFee) {
                        //商户优惠交易金额 */
                        mcMchntFeeDiscountTxnData.setMchntFeeDiscountTransAmt(remainderDiscountAmt.toString());
                        //手续费优惠值可能经过了重新手续费优惠计算有变化，所以重新赋值
                        mchntFeeDiscount = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeDiscount());
                    } else {
                        rglog.info("商户<{}> 重新计算手续费优惠失败，无手续费优惠!!!");
                        return CommonConstant.ONE;
                    }
                } else {
                    /* 限额小于累计优惠金额(当前包含本笔优惠金额),不可以优惠 */
                    rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>周期内新商户加本次已优惠<{}> 优惠上限<{}>，已超新商户优惠交易限额!", instId, mcNo, mcMchntFeeDiscountTxnData.getRuleIndex(), totalDiscount, discountLimit);
                    return CommonConstant.ONE;
                }
            }
        } else {
            //如果新商户上限为免手续费金额
            //本笔优惠手续费金额 + 周期统计累计优惠手续费金额 + 单日统计累计优惠手续费金额
            BigDecimal totalMchntFeeDiscount = mchntFeeDiscount.add(mchntTotalAmtAcc).add(mchntTotalAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("新商户周期内优惠上限<{}>,加本笔优惠手续费金额<{}>", discountLimit, totalMchntFeeDiscount);

            if (CommonConstant.ZERO <= discountLimit.compareTo(totalMchntFeeDiscount)) {
                rglog.info("法人机构<{}> 手续费优惠营销活动<{}> 规则<{}> 加本次已优惠<{}>优惠上限<{}>校验通过，未超规则限额!流程继续！", instId, mcNo, mcMchntFeeDiscountTxnData.getRuleIndex(), totalMchntFeeDiscount, discountLimit);
            } else {
                if (CommonConstant.ZERO >= discountLimit.compareTo(totalMchntFeeDiscount.subtract(mchntFeeDiscount))) {
                    rglog.info("商户<{}> 营销活动<{}> 不加本笔已累计优惠手续费金额<{}> 超出规则限制 <{}>,不予优惠！！！", mchntNo, mcNo, totalMchntFeeDiscount.subtract(mchntFeeDiscount), discountLimit);
                    return CommonConstant.ONE;
                } else {
                    mchntFeeDiscount = discountLimit.subtract(totalMchntFeeDiscount.subtract(mchntFeeDiscount));
                    rglog.info("商户<{}> 营销活动<{}> 不加本笔优惠手续费金额<{}> 未超过规则限制<{}>,仅可优惠剩余额度<{}>！！！", mchntNo, mcNo, totalMchntFeeDiscount.subtract(mchntFeeDiscount), discountLimit, mchntFeeDiscount);
                }
            }
        }

        //总预算 营销活动预算资金
        BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTxnData.getBudget());
        if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
            //总预算累计消耗金额  活动统计表+单日统计表+本笔交易中明细的汇总
            BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTxnData.getMcTotalAmtAcc()).add(mchntFeeDiscount);
            if (CommonConstant.ZERO <= budget.compareTo(mcTotalAmtAcc)) {
                rglog.info("商户<{}> 营销活动<{}> 加上本笔累计优惠金额<{}> 未超出总预算<{}>,给予优惠！！！", mchntNo, mcNo, mcTotalAmtAcc, budget);
            } else {
                rglog.info("加上本笔手续费优惠金额交易超出预算资金，继续判断不加本笔手续费优惠金额是否超出预算资金");
                if (CommonConstant.ZERO >= budget.compareTo(mcTotalAmtAcc.subtract(mchntFeeDiscount))) {
                    rglog.info("商户<{}> 营销活动<{}> 不加本笔已累计优惠金额<{}> 超出总预算<{}>,不予优惠！！！", mchntNo, mcNo, mcTotalAmtAcc.subtract(mchntFeeDiscount), budget);
                    return CommonConstant.ONE;
                } else {
                    rglog.info("商户<{}> 营销活动<{}> 不加本笔优惠金额<{}> 未超过总预算<{}>,仅可优惠剩余额度<{}>！！！", mchntNo, mcNo, mcTotalAmtAcc.subtract(mchntFeeDiscount), budget, budget.subtract(mcTotalAmtAcc.subtract(mchntFeeDiscount)));
                    mchntFeeDiscount = budget.subtract(mcTotalAmtAcc.subtract(mchntFeeDiscount));
                }
            }
        } else {
            rglog.info("默认预算资金无上限,不判断是否超出预算资金");
        }

        //重新给优惠手续费金额赋值
        mcMchntFeeDiscountTxnData.setMchntFeeDiscount(mchntFeeDiscount.toString());
        //重新给实收手续费赋值
        mcMchntFeeDiscountTxnData.setMchntFeeActual(mchntFeeReceivable.subtract(mchntFeeDiscount).toString());

        return CommonConstant.ZERO;
    }

    /**
     * 取新商户手续费优惠类营销活动各维度统计数据
     *
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/19 10:22
     */
    private int fetchNewMchntFeeDiscountMcQuotaData(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {

        //规则维度批量处理状态
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd_mchnt = CommonConstant.FLAG_NOT_SET;
        String instId = mcMchntFeeDiscountTxnData.getInstId();
        String mcNo = mcMchntFeeDiscountTxnData.getMcNo();
        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();
        String transDate = mcMchntFeeDiscountTxnData.getTransDate();
        String periodStartDate = mcMchntFeeDiscountTxnData.getPeriodStartDate();
        String periodEndDate = mcMchntFeeDiscountTxnData.getPeriodEndDate();
        String mcStartDate = mcMchntFeeDiscountTxnData.getMcStartDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String ruleIndex = mcMchntFeeDiscountTxnData.getRuleIndex();
        String mfdCriteriaCreateTimeTmp = mcMchntFeeDiscountTxnData.getMfdCriteriaCreateTime();
        String mfdCriteriaCreateTime = mfdCriteriaCreateTimeTmp.substring(0, 4) + mfdCriteriaCreateTimeTmp.substring(5, 7) + mfdCriteriaCreateTimeTmp.substring(8, 10);
        String mcType = mcMchntFeeDiscountTxnData.getMcType();

        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值 新增商户的这个值应该为0*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = periodStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据 新增商户的这个值应该为0*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, transDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }


        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, mcMchntFeeDiscountTxnData);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, mcMchntFeeDiscountTxnData);

        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay1 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, batchDate);
            if (null == tmStatMfdDay1) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
                tmStatMfdDay1 = new TMStatMfdDay();
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay1);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, transDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }


        //判断本笔交易明细中是否有参加相同活动的商户
        List<TMStatMfdDay> statMfdThisOrderList = statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList());
        //存在本笔交易同一活动数据
        if (statMfdThisOrderList.size() > 0) {
            //全局变量手续费营销活动单日统计表数据更新已优惠金额
            TMStatMfdDay tmStatMfdThisOrder = statMfdThisOrderList.get(0);
            BigDecimal totalAmtAccThisOrder = new BigDecimal(tmStatMfdThisOrder.getTotalAmtAcc());
            //把本订单使用相同活动的优惠金额累加
            statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList()).get(0).setTotalAmtAcc(totalAmtAccThisOrder.add(new BigDecimal((mcMchntFeeDiscountTxnData.getMchntFeeDiscount()))).toString());
        } else {
            //如果不存在 将子订单set
            TMStatMfdDay tmStatMfdThisOrder = new TMStatMfdDay();
            tmStatMfdThisOrder.setTotalAmtAcc(mcMchntFeeDiscountTxnData.getMchntFeeDiscount());
            tmStatMfdThisOrder.setInstId(instId);
            tmStatMfdThisOrder.setMcNo(mcNo);
            statMfdDayList.add(tmStatMfdThisOrder);
        }
        //将累计优惠手续费金额赋值
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, mcMchntFeeDiscountTxnData);

        return CommonConstant.ZERO;
    }

    /**
     * 检查 上送 订单明细 金额字段不能为负数
     *
     * @param paymentOrderDetailBean
     * @author ls
     * @date 2020/10/21
     */
    private void checkOrderDetailFieldHasNegativeNumber(PaymentOrderDetailBean paymentOrderDetailBean) {
        // 检查上传字段 不能为负数
        /* 商户清算金额	mchntSettleAmt*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getMchntSettleAmt()) && new BigDecimal(paymentOrderDetailBean.getMchntSettleAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /* 实收手续费金额  -- 商户应收手续费金额 */
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getMchntFeeReceivable()) && new BigDecimal(paymentOrderDetailBean.getMchntFeeReceivable()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /* 满减实际支付金额 */
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getMoneyOffTxnAmt()) && new BigDecimal(paymentOrderDetailBean.getMoneyOffTxnAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*满减补贴金额	moneyOffSubsidyTotal*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getMoneyOffSubsidyTotal()) && new BigDecimal(paymentOrderDetailBean.getMoneyOffSubsidyTotal()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*满减机构补贴金额	moneyOffSubsidyBank*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getMoneyOffSubsidyBank()) && new BigDecimal(paymentOrderDetailBean.getMoneyOffSubsidyBank()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*满减商户补贴金额	moneyOffSubsidyMchnt*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getMoneyOffSubsidyMchnt()) && new BigDecimal(paymentOrderDetailBean.getMoneyOffSubsidyMchnt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /* 手续费优惠金额	mchntFeeDiscount*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getMchntFeeDiscount()) && new BigDecimal(paymentOrderDetailBean.getMchntFeeDiscount()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*实收手续费金额	mchntFeeActual*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getMchntFeeActual()) && new BigDecimal(paymentOrderDetailBean.getMchntFeeActual()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /* 卡券面额	couponDenomination*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getCouponDenomination()) && new BigDecimal(paymentOrderDetailBean.getCouponDenomination()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*卡券购买金额	couponPurchaseAmt*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getCouponPurchaseAmt()) && new BigDecimal(paymentOrderDetailBean.getCouponPurchaseAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*卡券抵扣补贴金额	couponTotalSubsidy*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getCouponTotalSubsidy()) && new BigDecimal(paymentOrderDetailBean.getCouponTotalSubsidy()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*卡券机构补贴金额	couponBankSubsidy*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getCouponBankSubsidy()) && new BigDecimal(paymentOrderDetailBean.getCouponBankSubsidy()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*卡券商户补贴金额	couponMchntSubsidy*/
        if (!StringUtil.isNullorEmpty(paymentOrderDetailBean.getCouponMchntSubsidy()) && new BigDecimal(paymentOrderDetailBean.getCouponMchntSubsidy()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
    }

    /**
     * 判断是否存在免充值的对客营销活动，如果存在，需要重新计算应收手续费及商户清算金额字段
     *
     * @param mcMchntFeeDiscountTxnData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/27 09:36
     */
    private void checkIsExisNoRechargeToClientMc(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData, TBMchntBaseInfo mchntBaseInfo) throws BizException {

        String mchntNo = mchntBaseInfo.getMchntNo();

        rglog.info("开始判断商户（判断时使用的商户为请求上送的商户号）<{}> 是否有对客类免充值的营销活动.... ", mchntNo);

        //查询此商户是否已有对客类营销活动
        List<PaymentOrderDetailBean> paymentOrderDetailList = paymentOrderDetailBeanList.stream().filter(item -> item.getMchntNo().equals(mchntNo)).collect(Collectors.toList());
        ;
        //免充值活动补贴金额
        BigDecimal noRechargeMcDiscount = BigDecimal.ZERO;

        //判断是否存在对客类的营销活动
        if (!paymentOrderDetailList.isEmpty()) {
            for (PaymentOrderDetailBean paymentOrderDetailBean : paymentOrderDetailList) {
                String couponMcNo = paymentOrderDetailBean.getCouponMcNo();
                String moneyOffMcNo = paymentOrderDetailBean.getMoneyOffMcNo();

                //如果存在卡券类免充值的活动
                if (null != couponMcNo && CommonConstant.ZERO_COMMON_CONSTANT.equals(paymentOrderDetailBean.getCouponMchntSettleMethod())) {
                    noRechargeMcDiscount = noRechargeMcDiscount.add(new BigDecimal(paymentOrderDetailBean.getCouponTotalSubsidy()));
                }
                //如果存在减免类免充值的活动
                if (null != moneyOffMcNo && CommonConstant.ZERO_COMMON_CONSTANT.equals(paymentOrderDetailBean.getMoneyOffSettlementMethod())) {
                    noRechargeMcDiscount = noRechargeMcDiscount.add(new BigDecimal(paymentOrderDetailBean.getMoneyOffSubsidyTotal()));
                }
            }
        }

        rglog.info("商户<{}> ，对客类免充值营销活动总补贴金额 <{}>", mchntNo, noRechargeMcDiscount);

        //判断如果有免充值活动，则需要重新计算手续费信息
        if (noRechargeMcDiscount.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
            rglog.info("商户<{}> 有对客类免充值的营销活动，开始重新计算手续费各数据... ", mchntNo);

            //重新计算应收手续费金额
            Boolean isSuccess = calcMchntFee(mcMchntFeeDiscountTxnData, noRechargeMcDiscount, mchntBaseInfo);
            if (isSuccess) {
                rglog.info("商户<{}> 重新计算手续费成功,应收手续费<{}> 应收手续费费率<{}>", mchntNo, mcMchntFeeDiscountTxnData.getMchntFeeReceivable(), mcMchntFeeDiscountTxnData.getMchntFeeReceivableRate());
            } else {
                rglog.info("商户<{}> 重新计算手续费失败", mchntNo);
                throw new BizException(RespCodeEnum.FAILED_TO_DISCOUNT_FOR_MDF_MC_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_DISCOUNT_FOR_MDF_MC_ERROR.getRespDesc());
            }
        }
    }

    /**
     * 计算手续费
     * * @author liujinan
     *
     * @return int 返回码
     * @since 2020/10/27 09:36
     */
    public boolean calcMchntFee(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData, BigDecimal noRechargeMcDiscount, TBMchntBaseInfo mchntBaseInfo) {

        //商户清算金额（计算手续费的金额）需要减去免充值的活动的补贴金额
        BigDecimal relayMchnntSettleAmt = new BigDecimal(mcMchntFeeDiscountTxnData.getOrderAmt()).subtract(noRechargeMcDiscount);
        mcMchntFeeDiscountTxnData.setOrderAmt(relayMchnntSettleAmt.toString());
        mcMchntFeeDiscountTxnData.setMchntFeeDiscountTransAmt(relayMchnntSettleAmt.toString());

        String mchntNo = mchntBaseInfo.getMchntNo();
        String feeType = mcMchntFeeDiscountTxnData.getFeeType();
        String calMchntFeeBizeProdCode = mcMchntFeeDiscountTxnData.getCalMchntFeeBizProdCode();
        if (null == feeType || null == calMchntFeeBizeProdCode) {
            rglog.error("商户<{}> 存在免充值的对客营销活动，营销需要重新计算手续费信息，费率类型和计算手续费产品编码必须上送！", mchntNo);
            throw new BizException(RespCodeEnum.REQUEST_PARAMETER_LOST.getRespCode(), RespCodeEnum.REQUEST_PARAMETER_LOST.getRespDesc());
        }

        CalcMchntFeeResultBean calcMchntFeeResultBean;
        try {
            CalcMchntFeeBean calcMchntFeeBean = new CalcMchntFeeBean();
            calcMchntFeeBean.setInstId(mcMchntFeeDiscountTxnData.getInstId());
            calcMchntFeeBean.setMchntNo(mchntBaseInfo.getMchntNo());
            calcMchntFeeBean.setTransAmt(mcMchntFeeDiscountTxnData.getOrderAmt());
            calcMchntFeeBean.setIgasBizProdType(calMchntFeeBizeProdCode);
            calcMchntFeeBean.setSubProdType(feeType);
            calcMchntFeeBean.setStageCode("");
            calcMchntFeeBean.setStageNum("");
            CalcMchntFee calcMchntFee = new CalcMchntFee();
            calcMchntFeeResultBean = calcMchntFee.calcPayFee(calcMchntFeeBean);
            if (null == calcMchntFeeResultBean) {
                rglog.error("计算商户手续费失败,instId:<{}>,mchntNo:<{}>,transAmt:<{}>", mcMchntFeeDiscountTxnData.getInstId(), mchntBaseInfo.getMchntNo(), mcMchntFeeDiscountTxnData.getOrderAmt());
                return false;
            }
        } catch (Exception e) {
            rglog.error("商户<{}> 存在免充值的对客营销活动，重新计算商户应收手续费失败 <{}>！！！", mchntNo, e);
            return false;
        }

        if (calcMchntFeeResultBean == null) {
            rglog.error("商户<{}> 存在免充值的对客营销活动，重新计算商户应收手续费失败！！！", mchntNo);
            return false;
        }

        //重新设置手续费相关的参数
        mcMchntFeeDiscountTxnData.setMchntFeeReceivable(calcMchntFeeResultBean.getMchntFee());
        mcMchntFeeDiscountTxnData.setMchntFeeReceivableRate(calcMchntFeeResultBean.getFeeRate());

        return true;
    }

    /**
     * 校验用户参与优惠次数
     *
     * @return boolean
     * @author liujinan
     * @date 2020/11/11 16:36
     */
    public boolean checkIsUserReachLimit(Object mcInfoObject, List<TMMcUserInfo> tmMcUserInfoList) throws Exception {

        String mcNo, restriction, mcType, mcStartDate;
        //按活动类型获取数据
        if (mcInfoObject instanceof TMMcMoneyOffInfo) {
            mcNo = ((TMMcMoneyOffInfo) mcInfoObject).getMcNo();
            restriction = ((TMMcMoneyOffInfo) mcInfoObject).getRestriction();
            mcType = ((TMMcMoneyOffInfo) mcInfoObject).getMcType();
            mcStartDate = ((TMMcMoneyOffInfo) mcInfoObject).getMcStartDate();
        } else {
            mcNo = ((TMMcCouponInfo) mcInfoObject).getMcNo();
            restriction = ((TMMcCouponInfo) mcInfoObject).getRestriction();
            mcType = ((TMMcCouponInfo) mcInfoObject).getMcType();
            mcStartDate = ((TMMcCouponInfo) mcInfoObject).getMcStartDate();
        }

        //获取用户参与营销活动次数  当日的统计数据
        TMStat2CUserDayTransCount tmStat2CUserDayTransCount = getUserAttendMcCountDay(globalTxnDate, discountId, mcNo);
        tmStat2CUserDayTransCount.setMcType(mcType);
        tmStat2CUserDayTransCount.setMcStartDate(mcStartDate);
        int todayQtyAcc = tmStat2CUserDayTransCount.getDayPaymentCount();

        //当tmMcUserInfoList为null时活动为不指定用户
        if (null == tmMcUserInfoList) {
            if (userIdFlag.equals(CommonConstant.TWO_COMMON_CONSTANT)) {
                rglog.info("机构<{}> 营销活动<{}> 用户范围为所有用户，开始判断用户参与次数限制....", globalInstId, mcNo);
                boolean isReachUserLimit = isReachUserLimit(mcNo, tmStat2CUserDayTransCount, restriction);
                if (!isReachUserLimit)
                    return false;
            } else if (userIdFlag.equals(CommonConstant.THREE_COMMON_CONSTANT)) {
                int totalQtyAcc = 0;
                String Json = getUserList();
                rglog.info("用户编号字符串<{}>", Json);
                String a[] = Json.split(",");
                for (int i = 0; i < a.length; i++) {
                    //获取用户参与营销活动次数  当日的统计数据
                    TMStat2CUserDayTransCount newTmStat2CUserDayTransCount = getUserAttendMcCountDay(globalTxnDate, a[i], mcNo);
                    newTmStat2CUserDayTransCount.setMcType(mcType);
                    newTmStat2CUserDayTransCount.setMcStartDate(mcStartDate);
                    int userQtyAcc = selectUserCardQtyAcc(mcNo, newTmStat2CUserDayTransCount);
                    if (userQtyAcc == CommonConstant.MINUS_ONE) {
                        rglog.info("获取编号<{}>用户统计表数据异常", a[i]);
                        return false;
                    } else {
                        rglog.info("用户编号<{}>参与活动次数<{}>", a[i], userQtyAcc);
                        totalQtyAcc = totalQtyAcc + userQtyAcc;
                    }

                }
                rglog.info("上送多个userId<{}>总共参与活动次数<{}>", Json, totalQtyAcc);
                if (totalQtyAcc >= Integer.parseInt(restriction)) {
                    rglog.info("userId<{}>总共参与活动次数<{}>大于等于活动优惠次数<{}>，不予优惠", Json, totalQtyAcc, restriction);
                    return false;
                } else {
                    rglog.info("userId<{}>总共参与活动次数<{}>小于活动优惠次数<{}>，给予优惠", Json, totalQtyAcc, restriction);
                }
            } else {

            }
        } else {
            rglog.info("机构<{}> 营销活动<{}> 用户范围为指定用户范围，开始判断用户参与次数限制....", globalInstId, mcNo);
            //营销活动用户信息 指定用户不能配置多个，配置多个可能存在问题
            TMMcUserInfo tmMcUserInfo = tmMcUserInfoList.get(CommonConstant.ZERO);
            //账户类型
            String acctType = tmMcUserInfo.getAcctType();

            //当账户类型为手机号或银行卡号时校验优惠次数
            if (CommonConstant.ZERO_COMMON_CONSTANT.equals(acctType) || CommonConstant.ONE_COMMON_CONSTANT.equals(acctType)) {
                boolean isReachUserLimit = isReachUserLimit(mcNo, tmStat2CUserDayTransCount, restriction);
                if (!isReachUserLimit)
                    return false;
            }

            //当账户类型为卡bin或卡产品时校验优惠次数
            if (CommonConstant.TWO_COMMON_CONSTANT.equals(acctType) || CommonConstant.THREE_COMMON_CONSTANT.equals(acctType)) {

                //每日优惠次数需要限制
                if (null != tmMcUserInfo.getDayRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getDayRestriction())) {
                    //判断用户参与活动次数是否超过活动配置的限制次数
                    if (todayQtyAcc >= Integer.parseInt(tmMcUserInfo.getDayRestriction())) {
                        rglog.error("用户<{}> 营销活动<{}> 用户当日已参加此活动次数<{}> 大于等于单日最大限制<{}>，不可再参与本活动！", discountId, mcNo, todayQtyAcc, tmMcUserInfo.getDayRestriction());
                        return false;
                    }
                }

                //每周优惠次数需要限制
                if (null != tmMcUserInfo.getWeekRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getWeekRestriction())) {
                    boolean isReachUserWeekLimit = isReachUserWeekLimit(tmMcUserInfo, tmStat2CUserDayTransCount, mcNo);
                    if (!isReachUserWeekLimit)
                        return false;
                }

                //每月优惠次数需要限制
                if (null != tmMcUserInfo.getMonthRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getMonthRestriction())) {
                    boolean isReachUserMonthLimit = isReachUserMonthLimit(tmMcUserInfo, tmStat2CUserDayTransCount, mcNo);
                    if (!isReachUserMonthLimit)
                        return false;
                }

                //每季度优惠次数需要限制
                if (null != tmMcUserInfo.getQuerterRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getQuerterRestriction())) {
                    boolean isReachUserQuarterLimit = isReachUserQuarterLimit(tmMcUserInfo, tmStat2CUserDayTransCount, mcNo);
                    if (!isReachUserQuarterLimit)
                        return false;
                }

                //每年优惠次数需要限制
                if (null != tmMcUserInfo.getYearRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getYearRestriction())) {
                    boolean isReachUserYearLimit = isReachUserYearLimit(tmMcUserInfo, tmStat2CUserDayTransCount, mcNo);
                    if (!isReachUserYearLimit)
                        return false;
                }

                //整个活动期间优惠次数需要限制
                if (null != tmMcUserInfo.getRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getRestriction())) {
                    boolean isReachUserLimit = isReachUserLimit(mcNo, tmStat2CUserDayTransCount, tmMcUserInfo.getRestriction());
                    if (!isReachUserLimit)
                        return false;
                }
            }
        }
        return true;
    }

    /**
     * 获取对客营销活动用户单日统计表数据
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/12 23:40
     */
    private TMStat2CUserDay getToClientMcUserDayStatistics(String mcNo, String txnDate, String userId) throws Exception {

        /* 查询对客户营销活动用户单日统计表*/
        TMStat2CUserDay tmStat2CUserDay = selectToClientMcUserDayStatisticsByPK(globalInstId, mcNo, userId, txnDate);
        if (null == tmStat2CUserDay) {
            rglog.info("机构<{}> 营销活动<{}> 用户<{}> 日期<{}> 对客户营销活动用户单日统计表无数据!", globalInstId, mcNo, userId, txnDate);

            tmStat2CUserDay = new TMStat2CUserDay();
            tmStat2CUserDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CUserDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CUserDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        return tmStat2CUserDay;
    }

    /**
     * 获取对客营销活动用户月统计表数据
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/12 23:40
     */
    private TMStat2CUserMonth getToClientMcUserMonthStatistics(String mcNo, String month, String mcType, String mcStartDate, String userId) throws Exception {

        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String firstDayThisMonth = MompDateUtil.getCurrentMonthFirstDay();
        //当前月份
        String thisMonth = globalTxnDate.substring(0, 6);
        //当前月份的上个月
        String prevMonth = MompDateUtil.getBaseDateOffsetMonth(thisMonth, -1);
        //批量任务执行最后日期
        String batchDate, batchMonth;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "UserStatPeriod" + globalInstId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
            batchMonth = "";
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
            batchMonth = batchDate.substring(0, 6);
        }
        /* 查询对客户营销活动用户月统计表*/
        TMStat2CUserMonth tmStat2CUserMonth = selectToClientMcUserMonthStatisticsByPK(globalInstId, mcNo, userId, month);
        if (null == tmStat2CUserMonth) {
            rglog.info("机构<{}> 营销活动<{}> 用户<{}> 月份<{}> 对客户营销活动用户月统计表无数据!", globalInstId, mcNo, userId, month);
            //用户可能从来没有做过交易，也有可能是昨天做过，但是批量还没有处理完成
            tmStat2CUserMonth = new TMStat2CUserMonth();
            tmStat2CUserMonth.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CUserMonth.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CUserMonth.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }
        if (StringUtil.isNullorEmpty(batchMonth)) {
            //没有跑批记录 判断是不是活动开始的第一个月并且查询月是本月
            if (month.equals(mcStartDate.substring(0, 6)) && month.equals(thisMonth)) {
                //查询月是活动开始的月份 只需取单日明细表到活动开始日期
            } else {
                //查询月不是活动开始月 需取查询月1号到查询月最后一天的数据
                if (!month.equals(thisMonth)) {
                    lastDate = MompDateUtil.getMonthTheLastDay(month);
                }
                if (!month.equals(mcStartDate.substring(0, 6))) {
                    batchDate = month.concat("01");
                }
            }
        } else {//有跑批记录  判断最后跑批日期是不是在查询月内
            if (month.equals(batchMonth) && month.equals(thisMonth)) {
                //跑批日期在查询月内  需取昨天到最后跑批日期的单日明细
            } else {
                //判断查询月是否大于跑批最后月
                if (Integer.parseInt(batchMonth) < Integer.parseInt(month)) {
                    batchDate = month.concat("01");
                }
                if (!month.equals(thisMonth)) {
                    lastDate = MompDateUtil.getMonthTheLastDay(month);
                }
            }

        }

        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            TMStat2CUserDayTransCount TMStat2CUserDayTransCountDay = getUserAttendMcCountDay(batchDate, userId, mcNo);
            if (null == TMStat2CUserDayTransCountDay) {
                rglog.error("查询用户<{}>活动<{}>对客活动单日统计表 数据查询失败!", userId, mcNo);
                TMStat2CUserDayTransCountDay = new TMStat2CUserDayTransCount();
                TMStat2CUserDayTransCountDay.setDayPaymentCount(CommonConstant.ZERO);
                TMStat2CUserDayTransCountDay.setDayRefundCount(CommonConstant.ZERO);
            }
            copytmStat2CUserMonthData(tmStat2CUserMonth, TMStat2CUserDayTransCountDay);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }
        rglog.info("法人机构号<{}> 营销活动<{}> 用户<{}> 月份<{}> 获取统计数据完成，是否需要获取前一天的数据<{}> (0:不需要 1：需要)!", globalInstId, mcNo, userId, month, batchStatusStatMonth);
        return tmStat2CUserMonth;
    }

    /**
     * 获取对客营销活动用户统计表数据
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/12 23:40
     */
    private TMStat2CUser getToClientMcUserStatistics(String mcNo, String userId, String mcType, String mcStartDate) throws Exception {

        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);

        /* 查询对客户营销活动用户统计表*/
        TMStat2CUser tmStat2CUser = selectToClientMcUserStatisticsByPK(globalInstId, mcNo, userId);
        if (null == tmStat2CUser) {
            rglog.info("机构<{}> 营销活动<{}> 用户<{}> 对客户营销活动用户统计表无数据!", globalInstId, mcNo, userId);
            //用户可能从来没有做过交易，也有可能是昨天做过，但是批量还没有处理完成
            tmStat2CUser = new TMStat2CUser();
            tmStat2CUser.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CUser.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CUser.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "UserStat" + globalInstId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            TMStat2CUserDayTransCount TMStat2CUserDayTransCountDay = getUserAttendMcCountDay(batchDate, userId, mcNo);
            if (null == TMStat2CUserDayTransCountDay) {
                rglog.error("查询用户<{}>活动<{}>对客活动单日统计表 数据查询失败!", userId, mcNo);
                TMStat2CUserDayTransCountDay = new TMStat2CUserDayTransCount();
                TMStat2CUserDayTransCountDay.setDayPaymentCount(CommonConstant.ZERO);
                TMStat2CUserDayTransCountDay.setDayRefundCount(CommonConstant.ZERO);
            }
            copytmStat2CUserData(tmStat2CUser, TMStat2CUserDayTransCountDay);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }
        return tmStat2CUser;
    }

    /**
     * 查询用户某天已参与某个营销活动统计
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/12 10:10
     */
    private TMStat2CUserDayTransCount getUserAttendMcCountDay(String txnDate, String userId, String mcNo) throws Exception {
        rglog.info("机构<{}> 用户<{}> 营销活动编号<{}> 日期<{}> 开始获取用户已参加此活动次数", globalInstId, userId, mcNo, txnDate);

        String transStatus, bizStatus, txnNum, origTxnDate;
        int dayPaymentCount = 0, dayRefundCount = 0, weekRefundCount = 0, querterRefundCount = 0, monthRefundCount = 0, yearRefundCount = 0;

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();

        List<TMTxnOrderDet> userOrderDetialList = tmTxnOrderDetMapper.selectUserOrderDetailListInfo(globalInstId, txnDate, userId, mcNo);
        if (null == userOrderDetialList) {
            rglog.info("未获取到用户<{}> 营销活动<{}> 日期<{}> 的交易明细信息！", userId, mcNo, txnDate);
        } else {
            rglog.info("获取到用户<{}> 营销活动<{}> 日期<{}> 的交易明细信息,开始查询交易流水信息...", userId, mcNo, txnDate);

            for (TMTxnOrderDet tmTxnOrderDet : userOrderDetialList) {
                TMTxnOrder tmTxnOrder = tmTxnOrderMapper.selectTransactionOrderInfo(globalInstId, txnDate, tmTxnOrderDet.getFrontSeqNum());
                if (null == tmTxnOrder) {
                    rglog.error("未取到法人机构<{}> 日期<{}> 流水号<{}>的原始交易信息!", globalInstId, txnDate, tmTxnOrderDet.getFrontSeqNum());
                    throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
                }

                transStatus = tmTxnOrder.getTransStatus();
                bizStatus = tmTxnOrder.getBizStatus();
                txnNum = tmTxnOrder.getTxnNum();
                //如果交易是支付成功的
                if (TransStatusEnum.TRANS_SUCC.getStatus().equals(transStatus) &&
                        BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(bizStatus) &&
                        "P01MO003".equals(txnNum) && txnDate.equals(globalTxnDate)) {
                    rglog.info("获取到流水<{}> 为合并支付交易，且交易状态为成功!", tmTxnOrderDet.getFrontSeqNum());
                    dayPaymentCount++;
                } else if (!txnDate.equals(globalTxnDate) && TransStatusEnum.TRANS_SUCC.getStatus().equals(transStatus)
                        && "P01MO003".equals(txnNum) && (BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(bizStatus)
                        || BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode().equals(bizStatus)
                        || BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode().equals(bizStatus)
                        || BizStatusEnum.PROCESS_REGULATED.getBizStatusCode().equals(bizStatus))) {
                    //这样统计是因为昨天的批量任务没跑完 需要加上昨天交易今天退货的原正向交易笔数，因合并冲正没有流水，所以不需要加上原交易已经冲正的流水
                    rglog.info("获取到交易流水<{}>交易日期<{}>不是今天<{}>的合并支付交易,此交易为昨天交易今天退货或昨天交易昨天退货或昨天交易未退货的交易", tmTxnOrderDet.getFrontSeqNum(), txnDate, globalTxnDate);
                    dayPaymentCount++;
                } else {
                }

                //如果交易是退款成功的，或者冲正成功的,或调账成功
                if (TransStatusEnum.TRANS_SUCC.getStatus().equals(transStatus) &&
                        BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(bizStatus) &&
                        ("P04MO002".equals(txnNum) || "P02MO001".equals(txnNum) || "P08MO001".equals(txnNum))) {
                    origTxnDate = tmTxnOrder.getOrigTxnDate();
                    //原正向交易日期和退款/冲正日期是同一天，则此笔退款/冲正不纳入今天的统计,原正向交易日期不和退款/冲正同一天，则纳入当日的退款/冲正统计
                    if (!txnDate.equals(origTxnDate)) {
                        dayRefundCount++;
                        rglog.info("流水<{}> 交易为 <{}>，交易状态为成功,原交易日期<{}> 与退货日期<{}>不是同一天!", tmTxnOrderDet.getFrontSeqNum(), txnNum, origTxnDate, txnDate);
                    }

                    //获取的统计不是今天（一般是昨天的），此时由于上边流程中把退货的所有交易归为支付成功，由于我们不统计当天交易当天退货的笔数，所以在这里减去
                    if (!txnDate.equals(globalTxnDate) && txnDate.equals(origTxnDate)) {
                        dayPaymentCount--;
                        rglog.info("流水<{}> 交易为 <{}>，统计交易日期<{}>，当天交易当天发生退货，不统计到当天成功支付笔数!", tmTxnOrderDet.getFrontSeqNum(), txnNum, txnDate, origTxnDate);
                    }
                    //原正向交易的所在周和退款/冲正交易是否是在同一个周
                    LocalDate inputDate = LocalDate.parse(txnDate, DateTimeFormatter.BASIC_ISO_DATE);
                    LocalDate beginDayOfWeek = inputDate.with(DayOfWeek.MONDAY);

                    LocalDate origInputDate = LocalDate.parse(origTxnDate, DateTimeFormatter.BASIC_ISO_DATE);
                    LocalDate origBeginDayOfWeek = origInputDate.with(DayOfWeek.MONDAY);
                    if (beginDayOfWeek.isEqual(origBeginDayOfWeek) && !txnDate.equals(origTxnDate)) {
                        weekRefundCount++;
                        rglog.info("流水<{}> 交易为 <{}>，交易状态为成功,原交易日期<{}> 与退货日期在同一周!", tmTxnOrderDet.getFrontSeqNum(), txnNum, origTxnDate);
                    }

                    //原正向交易的月份和退款/冲正月份是同一个，则此笔退款/冲正不纳入当月的统计,原正向交易月份不和退款/冲正同一个，则纳入当月的退款/冲正统计
                    String txnMonth = txnDate.substring(0, 6);
                    String origTxnMonth = origTxnDate.substring(0, 6);
                    if (txnMonth.equals(origTxnMonth) && !txnDate.equals(origTxnDate)) {
                        monthRefundCount++;
                        rglog.info("流水<{}> 交易为 <{}>，交易状态为成功,原交易日期<{}> 与退货日期在同一月!", tmTxnOrderDet.getFrontSeqNum(), txnNum, origTxnDate);
                    }

                    //原正向交易的所在季度和退款/冲正交易是否是在同一个季度
                    Month month = inputDate.getMonth();
                    Month firstMonthOfQuarter = month.firstMonthOfQuarter();

                    Month origMonth = origInputDate.getMonth();
                    Month origFirstMonthOfQuarter = origMonth.firstMonthOfQuarter();

                    LocalDate quarterFirstDay = LocalDate.of(inputDate.getYear(), firstMonthOfQuarter, 1);
                    LocalDate oriQuarterFirstDay = LocalDate.of(origInputDate.getYear(), origFirstMonthOfQuarter, 1);

                    if (quarterFirstDay.isEqual(oriQuarterFirstDay) && !txnDate.equals(origTxnDate)) {
                        querterRefundCount++;
                        rglog.info("流水<{}> 交易为 <{}>，交易状态为成功,原交易日期<{}> 与退货日期在同一季度!", tmTxnOrderDet.getFrontSeqNum(), txnNum, origTxnDate);
                    }

                    //原正向交易的年份和退款/冲正年份是同一个，则此笔退款/冲正不纳入当月的统计,原正向交易年份不和退款/冲正同一个，则纳入当月的退款/冲正统计
                    String txnYear = txnDate.substring(0, 4);
                    String origTxnYear = origTxnDate.substring(0, 4);
                    if (txnYear.equals(origTxnYear) && !txnDate.equals(origTxnDate)) {
                        yearRefundCount++;
                        rglog.info("流水<{}> 交易为 <{}>，交易状态为成功,原交易日期<{}> 与退货日期在同一年!", tmTxnOrderDet.getFrontSeqNum(), txnNum, origTxnDate);
                    }
                }
            }
        }

        TMStat2CUserDayTransCount tmStat2CUserDayTransCount = new TMStat2CUserDayTransCount();
        tmStat2CUserDayTransCount.setInstId(globalInstId);
        tmStat2CUserDayTransCount.setMcNo(mcNo);
        tmStat2CUserDayTransCount.setTransDate(txnDate);
        tmStat2CUserDayTransCount.setUserId(userId);
        tmStat2CUserDayTransCount.setDayPaymentCount(dayPaymentCount);
        tmStat2CUserDayTransCount.setDayRefundCount(dayRefundCount);
        tmStat2CUserDayTransCount.setWeekRefundCount(weekRefundCount);
        tmStat2CUserDayTransCount.setMonthRefundCount(monthRefundCount);
        tmStat2CUserDayTransCount.setQuerterRefundCount(querterRefundCount);
        tmStat2CUserDayTransCount.setYearRefundCount(yearRefundCount);

        return tmStat2CUserDayTransCount;
    }

    /**
     * 用户参与活动 周维度是否超限
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/13 23:40
     */
    private boolean isReachUserWeekLimit(TMMcUserInfo tmMcUserInfo, TMStat2CUserDayTransCount tmStat2CUserDayTransCount, String mcNo) throws Exception {
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        int todayQtyAcc = tmStat2CUserDayTransCount.getDayPaymentCount();
        String userId = tmStat2CUserDayTransCount.getUserId();

        //累计优惠笔数
        int totalQtyAccWeek = 0;

        LocalDate inputDate = LocalDate.parse(globalTxnDate, DateTimeFormatter.BASIC_ISO_DATE);
        LocalDate beginDayOfWeek = inputDate.with(DayOfWeek.MONDAY);
        String firstDayOfWeek = beginDayOfWeek.toString().replaceAll("-", "");

        //今天是周的第一天，则总优惠笔数即为今天发生的优惠笔数
        if (globalTxnDate.equals(firstDayOfWeek))
            totalQtyAccWeek = todayQtyAcc;
        else {
            int i = 0;
            boolean isGetBeforeSecondData = false;
            TMStat2CUserDay tmStat2CUserDay;

            String date = firstDayOfWeek;
            //今天不是周的第一天，则取前一天的数据，判断前一天是否有数据，如果没有则需要取昨天的前一天的数据
            while (i < 6) {
                i++;
                if (globalTxnDate.equals(date)) {
                    //如果获取日期已经是今天了，则退出
                    break;
                }

                //当日的统计数据
                tmStat2CUserDay = getToClientMcUserDayStatistics(mcNo, date, userId);
                totalQtyAccWeek = totalQtyAccWeek + Integer.parseInt(tmStat2CUserDay.getTotalQtyAcc());

                //判断当前获取的日统计数据为昨日的
                if (lastDate.equals(date)) {
                    //当获取到的昨日单日统计数据为0时，则需要自己获取昨天的数据
                    if (CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStat2CUserDay.getTotalQtyAcc()))
                        isGetBeforeSecondData = true;
                }

                date = DateUtil.getBaseDateOffsetDay(date, 1);
            }

            if (isGetBeforeSecondData) {
                //获取昨日统计数据
                //获取的数据累加到活动统计中
                TMStat2CUserDayTransCount tmStat2CUserDayTransCountLastDay = getUserAttendMcCountDay(lastDate, userId, mcNo);

                totalQtyAccWeek = totalQtyAccWeek + tmStat2CUserDayTransCountLastDay.getDayPaymentCount() - tmStat2CUserDayTransCountLastDay.getWeekRefundCount();
            }

            //加上当日的统计值
            totalQtyAccWeek = totalQtyAccWeek + todayQtyAcc - tmStat2CUserDayTransCount.getWeekRefundCount();
        }

        //判断用户参与活动次数是否超过活动配置的限制次数
        if (totalQtyAccWeek >= Integer.parseInt(tmMcUserInfo.getWeekRestriction())) {
            rglog.error("用户<{}> 营销活动<{}> 用户当前周已参加此活动次数<{}> 大于等于单周最大限制<{}>，不可再参与本活动！", userId, mcNo, totalQtyAccWeek, tmMcUserInfo.getWeekRestriction());
            return false;
        }

        return true;
    }

    /**
     * 用户参与活动 月维度是否超限
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/13 23:40
     */
    private boolean isReachUserMonthLimit(TMMcUserInfo tmMcUserInfo, TMStat2CUserDayTransCount tmStat2CUserDayTransCount, String mcNo) throws Exception {

        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String month = globalTxnDate.substring(0, 6);
        int todayQtyAcc = tmStat2CUserDayTransCount.getDayPaymentCount();
        String mcType = tmStat2CUserDayTransCount.getMcType();
        String mcStartDate = tmStat2CUserDayTransCount.getMcStartDate();
        String userId = tmStat2CUserDayTransCount.getUserId();


        TMStat2CUserMonth tmStat2CUserMonth = getToClientMcUserMonthStatistics(mcNo, month, mcType, mcStartDate, userId);

        if (null == tmStat2CUserMonth) {
            rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}> 统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, month);
            return false;
        }

        //累计优惠笔数
        int totalQtyAcc = Integer.parseInt(tmStat2CUserMonth.getTotalQtyAcc());

        //活动统计的加当日统计的
        totalQtyAcc = totalQtyAcc + todayQtyAcc - tmStat2CUserDayTransCount.getMonthRefundCount();

        rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数<{}>,活动配置的每个用户每月最多参与次数<{}>", userId, mcNo, totalQtyAcc, tmMcUserInfo.getMonthRestriction());
        //判断用户参与活动次数是否超过活动配置的限制次数
        if (totalQtyAcc >= Integer.parseInt(tmMcUserInfo.getMonthRestriction())) {
            rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数大于等于每月最大限制，不可再参与本活动！", userId, mcNo);
            return false;
        }

        return true;
    }

    /**
     * 用户参与活动 季度维度是否超限
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/13 23:40
     */
    private boolean isReachUserQuarterLimit(TMMcUserInfo tmMcUserInfo, TMStat2CUserDayTransCount tmStat2CUserDayTransCount, String mcNo) throws Exception {

        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        int todayQtyAcc = tmStat2CUserDayTransCount.getDayPaymentCount();
        String mcType = tmStat2CUserDayTransCount.getMcType();
        String mcStartDate = tmStat2CUserDayTransCount.getMcStartDate();
        String userId = tmStat2CUserDayTransCount.getUserId();

        //当前月份
        String nowMonth = globalTxnDate.substring(0, 6);
        //上个月
        String lastMonth = MompDateUtil.getBaseDateOffsetMonth(nowMonth, -1);
        //上个月是否取前一天的数据
        int batchStatusStatLastMonth = CommonConstant.FLAG_NOT_SET;

        //累计优惠笔数
        int totalQtyAccQuarter = 0;

        //获取当前日期季度的第一天
        LocalDate inputDate = LocalDate.parse(globalTxnDate, DateTimeFormatter.BASIC_ISO_DATE);
        Month month = inputDate.getMonth();
        Month firstMonthOfQuarter = month.firstMonthOfQuarter();
        LocalDate quarterFirstDay = LocalDate.of(inputDate.getYear(), firstMonthOfQuarter, 1);
        String firstDayOfQuarter = quarterFirstDay.toString().replaceAll("-", "");

        String quarterFirstMonth = firstDayOfQuarter.substring(0, 6);
        //活动开始月
        String mcMonth = mcStartDate.substring(0, 6);

        //获取月统计表数据
        //今天是季度的第一个月，则季度值为月统计表中本月的统计值
        if (nowMonth.equals(quarterFirstMonth)) {
            TMStat2CUserMonth tmStat2CUserMonth = getToClientMcUserMonthStatistics(mcNo, nowMonth, mcType, mcStartDate, userId);

            if (null == tmStat2CUserMonth) {
                rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}> 统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, nowMonth);
                return false;
            }

            //累计优惠笔数
            totalQtyAccQuarter = Integer.parseInt(tmStat2CUserMonth.getTotalQtyAcc());

        } else {
            int i = 0;
            String everyMonth = quarterFirstMonth;
            //取当前季度每个月的统计值
            while (i < 3) {
                i++;
                if (new BigDecimal(mcMonth).compareTo(new BigDecimal(everyMonth)) > 0) {
                    rglog.info("活动开始月<{}>大于查询月<{}>，跳过查询", mcMonth, everyMonth);
                    everyMonth = MompDateUtil.getBaseDateOffsetMonth(everyMonth, 1);
                    continue;
                }
                TMStat2CUserMonth tmStat2CUserMonth = getToClientMcUserMonthStatistics(mcNo, everyMonth, mcType, mcStartDate, userId);

                if (null == tmStat2CUserMonth) {
                    rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}> 统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, everyMonth);
                    return false;
                }

                //累计优惠笔数
                totalQtyAccQuarter = totalQtyAccQuarter + Integer.parseInt(tmStat2CUserMonth.getTotalQtyAcc());


                //如果当前获取的月份统计值即为当前日期所在的月，则循环结束
                if (nowMonth.equals(everyMonth))
                    break;

                everyMonth = MompDateUtil.getBaseDateOffsetMonth(everyMonth, 1);
            }
        }


        //活动统计的加当日统计的
        totalQtyAccQuarter = totalQtyAccQuarter + todayQtyAcc - tmStat2CUserDayTransCount.getQuerterRefundCount();

        //判断用户参与活动次数是否超过活动配置的限制次数
        if (totalQtyAccQuarter >= Integer.parseInt(tmMcUserInfo.getQuerterRestriction())) {
            rglog.error("用户<{}> 营销活动<{}> 用户当前季度已参加此活动次数<{}> 大于等于单季度最大限制<{}>，不可再参与本活动！", userId, mcNo, totalQtyAccQuarter, tmMcUserInfo.getQuerterRestriction());
            return false;
        }

        return true;
    }

    /**
     * 用户参与活动 年维度是否超限
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/13 23:40
     */
    private boolean isReachUserYearLimit(TMMcUserInfo tmMcUserInfo, TMStat2CUserDayTransCount tmStat2CUserDayTransCount, String mcNo) throws Exception {

        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        int todayQtyAcc = tmStat2CUserDayTransCount.getDayPaymentCount();
        String mcType = tmStat2CUserDayTransCount.getMcType();
        String mcStartDate = tmStat2CUserDayTransCount.getMcStartDate();
        String userId = tmStat2CUserDayTransCount.getUserId();

        //当前月份
        String nowMonth = globalTxnDate.substring(0, 6);
        //累计优惠笔数
        int totalQtyAccYear = 0;

        //获取当前日期季度的第一天
        LocalDate inputDate = LocalDate.parse(globalTxnDate, DateTimeFormatter.BASIC_ISO_DATE);
        LocalDate quarterFirstDay = LocalDate.of(inputDate.getYear(), Month.JANUARY, 1);
        String firstDayOfQuarter = quarterFirstDay.toString().replaceAll("-", "");

        String yearFirstMonth = firstDayOfQuarter.substring(0, 6);

        //上个月
        String lastMonth = MompDateUtil.getBaseDateOffsetMonth(nowMonth, -1);
        //上个月是否取前一天的数据
        int batchStatusStatLastMonth = CommonConstant.FLAG_NOT_SET;
        //活动开始月
        String mcMonth = mcStartDate.substring(0, 6);

        //获取月统计表数据
        //今天在今年的第一个月，则年统计值为月统计表中本月的统计值
        if (nowMonth.equals(yearFirstMonth)) {
            TMStat2CUserMonth tmStat2CUserMonth = getToClientMcUserMonthStatistics(mcNo, nowMonth, mcType, mcStartDate, userId);

            if (null == tmStat2CUserMonth) {
                rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}>统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, nowMonth);
                return false;
            }

            //累计优惠笔数
            totalQtyAccYear = Integer.parseInt(tmStat2CUserMonth.getTotalQtyAcc());

        } else {
            int i = 0;
            String everyMonth = yearFirstMonth;
            //取当年每个月的统计值
            while (i < 12) {
                i++;
                if (new BigDecimal(mcMonth).compareTo(new BigDecimal(everyMonth)) > 0) {
                    rglog.info("活动开始月<{}>大于查询月<{}>，跳过查询", mcMonth, everyMonth);
                    everyMonth = MompDateUtil.getBaseDateOffsetMonth(everyMonth, 1);
                    continue;
                }
                TMStat2CUserMonth tmStat2CUserMonth = getToClientMcUserMonthStatistics(mcNo, everyMonth, mcType, mcStartDate, userId);

                if (null == tmStat2CUserMonth) {
                    rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}>统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, everyMonth);
                    return false;
                }

                //累计优惠笔数
                totalQtyAccYear = totalQtyAccYear + Integer.parseInt(tmStat2CUserMonth.getTotalQtyAcc());


                //如果当前获取的月份统计值即为当前日期所在的月，则循环结束
                if (nowMonth.equals(everyMonth))
                    break;

                everyMonth = MompDateUtil.getBaseDateOffsetMonth(everyMonth, 1);
            }
        }


        //活动统计的加当日统计的
        totalQtyAccYear = totalQtyAccYear + todayQtyAcc - tmStat2CUserDayTransCount.getYearRefundCount();

        //判断用户参与活动次数是否超过活动配置的限制次数
        if (totalQtyAccYear >= Integer.parseInt(tmMcUserInfo.getYearRestriction())) {
            rglog.error("用户<{}> 营销活动<{}> 用户当年已参加此活动次数<{}> 大于等于每年最大限制<{}>，不可再参与本活动！", userId, mcNo, totalQtyAccYear, tmMcUserInfo.getYearRestriction());
            return false;
        }

        return true;
    }

    /**
     * 用户参与活动 整个活动期间是否超限
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/13 23:40
     */
    private boolean isReachUserLimit(String mcNo, TMStat2CUserDayTransCount tmStat2CUserDayTransCount, String restriction) throws Exception {

        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        int todayQtyAcc = tmStat2CUserDayTransCount.getDayPaymentCount();
        String mcType = tmStat2CUserDayTransCount.getMcType();
        String mcStartDate = tmStat2CUserDayTransCount.getMcStartDate();
        String userId = tmStat2CUserDayTransCount.getUserId();
        rglog.info("用户<{}> 营销活动<{}>该用户当日已参加此活动次数<{}>", userId, mcNo, todayQtyAcc);

        //获取对客营销活动用户统计表数据
        TMStat2CUser tmStat2CUser = getToClientMcUserStatistics(mcNo, userId, mcType, mcStartDate);

        if (null == tmStat2CUser) {
            rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取对客营销活动用户统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId);
            return false;
        }

        //累计优惠笔数
        int totalQtyAcc = Integer.parseInt(tmStat2CUser.getTotalQtyAcc());

        //活动统计的加当日统计的正向交易减去当日退货
        totalQtyAcc = totalQtyAcc + todayQtyAcc - tmStat2CUserDayTransCount.getDayRefundCount();

        rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数<{}>,活动配置的每个用户限制最多参与次数<{}>", userId, mcNo, totalQtyAcc, restriction);
        //判断用户参与活动次数是否超过活动配置的限制次数
        if (totalQtyAcc >= Integer.parseInt(restriction)) {
            rglog.info("用户<{}> 营销活动<{}>该用户已参加此活动次数大于等于最大限制，不可再参与本活动！", userId, mcNo);
            return false;
        }

        return true;
    }

    /**
     * 使用主键获取对客营销活动用户统计表单条数据
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/11 23:40
     */
    private TMStat2CUser selectToClientMcUserStatisticsByPK(String instId, String mcNo, String memberId) throws Exception {

        TMStat2CUserMapper tmStat2CUserMapper = new TMStat2CUserMapperImpl();

        TMStat2CUser tmStat2CUser = new TMStat2CUser();
        tmStat2CUser.setInstId(instId);
        tmStat2CUser.setMcNo(mcNo);
        tmStat2CUser.setMemberId(memberId);

        return tmStat2CUserMapper.selectToClientMcUserStatistics(tmStat2CUser);
    }

    /**
     * 使用主键获取对客营销活动用户月统计表单条数据
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/12 23:40
     */
    private TMStat2CUserMonth selectToClientMcUserMonthStatisticsByPK(String instId, String mcNo, String memberId, String month) throws Exception {

        TMStat2CUserMonthMapper tmStat2CUserMonthMapper = new TMStat2CUserMonthMapperImpl();

        TMStat2CUserMonth tmStat2CUserMonth = new TMStat2CUserMonth();
        tmStat2CUserMonth.setInstId(instId);
        tmStat2CUserMonth.setMcNo(mcNo);
        tmStat2CUserMonth.setMemberId(memberId);
        tmStat2CUserMonth.setMonth(month);

        return tmStat2CUserMonthMapper.selectToClientMcUserMonthStatistics(tmStat2CUserMonth);
    }

    /**
     * 使用主键获取对客营销活动用户单日统计表单条数据
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/12 23:40
     */
    private TMStat2CUserDay selectToClientMcUserDayStatisticsByPK(String instId, String mcNo, String memberId, String txnDate) throws Exception {

        TMStat2CUserDayMapper tmStat2CUserDayMapper = new TMStat2CUserDayMapperImpl();

        TMStat2CUserDay tmStat2CUserDay = new TMStat2CUserDay();
        tmStat2CUserDay.setInstId(instId);
        tmStat2CUserDay.setMcNo(mcNo);
        tmStat2CUserDay.setMemberId(memberId);
        tmStat2CUserDay.setTxnDate(txnDate);

        return tmStat2CUserDayMapper.selectToClientMcUserDayStatistics(tmStat2CUserDay);
    }

    /**
     * 商户手续费优惠活动查询营销活动商户信息
     *
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntInfo 商户基本信息表T_B_MCHNT_BASE_INFO
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2021/2/26 10:13
     */
    private List<TMMcMchntInfo> selectMcMchntInfoListByMcNo(String instId, String mcNo, String mchntType) throws Exception {

        TMMcMchntInfo mcMchntInfo = new TMMcMchntInfo();
        mcMchntInfo.setInstId(instId);
        mcMchntInfo.setMcNo(mcNo);
        mcMchntInfo.setMchntType(mchntType);

        McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
        return mcMchntInfoMapper.selectMcMchntInfoListByMcNo(instId, mcNo, mchntType);
    }

    /**
     * 判断活动是否区分商户性质的才能参加
     *
     * @author liujinan
     * @date 2021/3/21 10:13
     */
    private void JudgeMcDiscriminateMchntNature(List<TMMcMchntFeeDiscountInfo> inputTmMcMchntFeeDiscountInfo, List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {
        if (CommonConstant.ZERO < inputTmMcMchntFeeDiscountInfo.size()) {
            if (CommonConstant.INST_ID_815.equals(globalInstId)) {
                JudgeMcDiscriminateMchntNature815(inputTmMcMchntFeeDiscountInfo, tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, mcMchntFeeDiscountTxnData);
            } else {
                JudgeMcDiscriminateMchntNatureOthers(inputTmMcMchntFeeDiscountInfo, tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, mcMchntFeeDiscountTxnData);
            }
        } else {
            rglog.info("法人机构<{}>的商户<{}>未找到适合的支持新增商户的营销活动,该商户无法享受任何商户手续费优惠活动!", globalInstId, mcMchntFeeDiscountTxnData.getMchntNo());
        }
    }

    /**
     * 商户基本信息转存
     *
     * @throws Exception 异常信息
     * @author liujinan
     */
    private void copyMchntBaseInfo(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData, TBMchntBaseInfo mchntBaseInfo) {
        //商户号
        mcMchntFeeDiscountTxnData.setMchntNo(mchntBaseInfo.getMchntNo());
        // 机构编码
        mcMchntFeeDiscountTxnData.setInstId(mchntBaseInfo.getInstId());
        // 商户类型
        mcMchntFeeDiscountTxnData.setMchntType(mchntBaseInfo.getMchntType());
        // 商户名称
        mcMchntFeeDiscountTxnData.setMchntName(mchntBaseInfo.getMchntName());
        // 所属商圈
        mcMchntFeeDiscountTxnData.setMchntArea(mchntBaseInfo.getMchntArea());
        // 商户入驻时间
        mcMchntFeeDiscountTxnData.setMchntExpandTime(mchntBaseInfo.getMchntExpandTime());
        // 企业性质
        mcMchntFeeDiscountTxnData.setMchntNature(mchntBaseInfo.getMchntNature());
        //商户签约机构
        mcMchntFeeDiscountTxnData.setSignInstId(mchntBaseInfo.getSignInstId());
    }

    /**
     * 潍坊行老平台营销规则检查
     *
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/5/14 14:40
     */
    private boolean checkWeiFangOldRule(TMMcMoneyOffInfo tmMcMoneyOffInfo) throws Exception {
        String mcNo = tmMcMoneyOffInfo.getMcNo();
        rglog.info("根据机构号<{}>活动号<{}>查询卡产品信息", globalInstId, mcNo);
        McUserInfoMapper mcUserInfoMapper = new McUserInfoMapperImpl();
        List<TMMcUserInfo> userInfoList = mcUserInfoMapper.selectMcUserInfoList(globalInstId, mcNo);
        if (null == userInfoList) {
            rglog.info("未查询到卡产品信息");
        } else {
            rglog.info("查询到卡产品信息<{}>条", userInfoList.size());
        }
        TPSignAcctInfoMapper tpSignAcctInfoMapper = new TPSignAcctInfoMapperImpl();
        rglog.info("根据卡号<{}>查询用户签约信息", discountId);
        TPSignAcctInfo tpSignAcctInfo = new TPSignAcctInfo();
        tpSignAcctInfo.setInstId(globalInstId);
        //70 无感支付
        tpSignAcctInfo.setSignTokenType("70");
        tpSignAcctInfo.setSignAcctNo(discountId);
        TPSignAcctInfo tpSignAcctInfos = tpSignAcctInfoMapper.selectSignAcctByInstIdTokenTypeAcctNo(tpSignAcctInfo);
        if (null == tpSignAcctInfos) {
            rglog.info("根据卡号<{}>查询用户签约信息失败", discountId);
            return false;
        }
        //身份证号
        String certNo = tpSignAcctInfos.getCertNo();
        tpSignAcctInfo = new TPSignAcctInfo();
        tpSignAcctInfo.setInstId(globalInstId);
        //70 无感支付
        tpSignAcctInfo.setSignTokenType("70");
        tpSignAcctInfo.setCertNo(certNo);
        List<TPSignAcctInfo> tpSignAcctInfoList = tpSignAcctInfoMapper.selectSignAcctByInstIdUserIdTokenTypeCertNo(tpSignAcctInfo);
        if (null == tpSignAcctInfoList || tpSignAcctInfoList.isEmpty()) {
            rglog.info("根据身份证号<{}>查询用户签约信息失败", certNo);
            return false;
        }

        //用户下所有卡参与次数
        int todayQtyAcc = 0;
        //普卡5次
        int restriction = 8;
        //判断是否存在车主卡 存在车主卡8+15次
        if (null != userInfoList && !userInfoList.isEmpty()) {
            for (TMMcUserInfo tmMcUserInfo : userInfoList) {
                List<TPSignAcctInfo> carList = tpSignAcctInfoList.stream().filter(item -> item.getSignAcctNo().substring(0, 10).equals(tmMcUserInfo.getAcctNo())).collect(Collectors.toList());
                if (null != carList && !carList.isEmpty()) {
                    restriction = 23;
                    break;
                }
            }
        }
        rglog.info("获取身份证号<{}>下卡号参与营销活动次数", certNo);
        for (TPSignAcctInfo newTpSignAcctInfo : tpSignAcctInfoList) {
            TMStat2CUserDayTransCount tmStat2CUserDayTransCount = getUserAttendMcCountDay(globalTxnDate, newTpSignAcctInfo.getSignAcctNo(), mcNo);
            tmStat2CUserDayTransCount.setMcType(tmMcMoneyOffInfo.getMcType());
            tmStat2CUserDayTransCount.setMcStartDate(tmMcMoneyOffInfo.getMcStartDate());
            int cardQtyAcc = selectUserCardQtyAcc(mcNo, tmStat2CUserDayTransCount);
            if (cardQtyAcc == CommonConstant.MINUS_ONE) {
                rglog.info("获取卡号<{}>用户统计表数据异常", newTpSignAcctInfo.getSignAcctNo());
                return false;
            } else {
                todayQtyAcc = todayQtyAcc + cardQtyAcc;
            }
        }
        rglog.info("机构<{}> 营销活动<{}> 用户下所有卡号已参与次数<{}>，开始判断用户参与次数限制....", globalInstId, mcNo, todayQtyAcc);
        if (todayQtyAcc >= restriction) {
            rglog.info("用户下所有卡号已参与次数<{}>大于等于优惠次数<{}>，本次不予优惠", todayQtyAcc, restriction);
            return false;
        } else {
            rglog.info("用户下所有卡号已参与次数<{}>小于优惠次数<{}>，本次给予优惠", todayQtyAcc, restriction);
            return true;
        }


    }

    /**
     * 获取userId参与活动次数
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/13 23:40
     */
    private int selectUserCardQtyAcc(String mcNo, TMStat2CUserDayTransCount tmStat2CUserDayTransCount) throws Exception {
        String userId = tmStat2CUserDayTransCount.getUserId();
        String mcType = tmStat2CUserDayTransCount.getMcType();
        String mcStartDate = tmStat2CUserDayTransCount.getMcStartDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        int todayQtyAcc = tmStat2CUserDayTransCount.getDayPaymentCount();
        rglog.info("卡号<{}> 营销活动<{}>该卡号当日已参加此活动次数<{}>", userId, mcNo, todayQtyAcc);

        //获取对客营销活动用户统计表数据
        TMStat2CUser tmStat2CUser = getToClientMcUserStatistics(mcNo, userId, mcType, mcStartDate);

        if (null == tmStat2CUser) {
            rglog.error("机构<{}> 对客营销活动<{}> 卡号<{}> 获取对客营销活动用户统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId);
            return CommonConstant.MINUS_ONE;
        }

        //累计优惠笔数
        int totalQtyAcc = Integer.parseInt(tmStat2CUser.getTotalQtyAcc());


        //活动统计的加当日统计的正向交易减去当日退货
        totalQtyAcc = totalQtyAcc + todayQtyAcc - tmStat2CUserDayTransCount.getDayRefundCount();

        rglog.info("卡号<{}> 营销活动<{}>该卡号已参加此活动次数<{}>", userId, mcNo, totalQtyAcc);

        return totalQtyAcc;
    }

    /**
     * 判断活动是否区分商户性质的才能参加--815济宁行处理流程
     *
     * @author liujinan
     * @date 2021/5/12 10:13
     */
    private void JudgeMcDiscriminateMchntNature815(List<TMMcMchntFeeDiscountInfo> inputTmMcMchntFeeDiscountInfo, List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {
        //当前商户号
        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();
        //当前商户的性质 01-小微商户 02-个体工商户 03-企业 04-党政 05-机关及事业单位 99-其他组织
        String mchntNature = mcMchntFeeDiscountTxnData.getMchntNature();
        rglog.info("当前商户<{}> 企业性质为<{}> 01-小微商户 02-个体工商户 03-企业 04-党政 05-机关及事业单位 99-其他组织", mchntNo, mchntNature);

        //查询商户的结算账户
        rglog.info("查询商户<{}> 的结算账户信息!", mcMchntFeeDiscountTxnData.getMchntNo());
        /*商户结算信息正式表*/
        McMchntAcctInfoMapper mcMchntAcctInfoMapper = new McMchntAcctInfoMapperImpl();
        MchntAcctInfo mchntAcctInfo = mcMchntAcctInfoMapper.selectMchntAcctInfoByPrimaryKey(globalInstId, mchntNo, "*", FundTypeEnum.SETTLE_TYPE.getFundCode());

        /* 判断活动是否区分商户性质参加，如果区分，则判断当前商户是否符合条件 */
        for (TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo : inputTmMcMchntFeeDiscountInfo) {
            //当前活动支持的商户类型
            String avySprtMrctTypString = tmMcMchntFeeDiscountInfo.getavySprtMrctTyp();
            if (null == avySprtMrctTypString ||
                    CommonConstant.EMPTY_STRING.equals(avySprtMrctTypString) ||
                    CommonConstant.SUPPORT_ALLTYPES_MCHNT.equals(avySprtMrctTypString)) {
                rglog.info("营销活动<{}> 支持所有类型的商户参加,无需校验当前商户的性质", tmMcMchntFeeDiscountInfo.getMcNo());
                tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
            } else {
                //当前活动支持的商户性质 小微商户|个体工商户|企业|党政|机关及事业单位|其他组织
                String[] avySprtMrctTyp = avySprtMrctTypString.split(CommonConstant.VERTICAL_LINE);

                if (CommonConstant.SIX != avySprtMrctTyp.length) {
                    rglog.error("营销活动<{}> 配置的支持参加的商户类型异常,商户无法参加本活动！", tmMcMchntFeeDiscountInfo.getMcNo());
                    continue;
                }

                String settleAcctType = "";
                if (null != mchntAcctInfo) {
                    //结算账户类型
                    settleAcctType = mchntAcctInfo.getSettleAcctType();
                    if (AcctTypeEnum.OWN_CORPORATE_ACCOUNT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OTHER_CORPORATE_ACCOUNT.getAcctType().equals(settleAcctType)) {
                        rglog.info("当前商户<{}> 结算账户类型<{}> 结算账户为对公户，对公户需要参与针对企业商户的营销活动，判断当前营销活动是否满足!", mchntNo, settleAcctType);
                        if (!CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[2])) {
                            rglog.error("当前活动<{}> 不支持企业类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                        } else {
                            rglog.info("当前活动<{}> 支持企业类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        }
                    } else if (AcctTypeEnum.OWN_DEBIT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OWN_CREDIT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OWN_BANK_BOOK.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OTHER_DEBIT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OTHER_CREDIT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OTHER_BANK_BOOK.getAcctType().equals(settleAcctType)) {
                        rglog.info("当前商户<{}> 结算账户类型<{}> 结算账户为对私户，小微商户参与小微商户的活动，其他类型的商户参与个体商户的营销活动!", mchntNo, settleAcctType);
                        if ("01".equals(mchntNature)) {
                            //判断当前商户是否支持小微企业的营销活动
                            if (!CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[0])) {
                                rglog.error("当前活动<{}> 不支持小微类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                            } else {
                                rglog.info("当前活动<{}> 支持小微类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                                tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                            }
                        } else {
                            //判断当前商户是否支持个体的营销活动
                            if (!CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[1])) {
                                rglog.error("当前活动<{}> 不支持个体类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                            } else {
                                rglog.info("当前活动<{}> 支持个体类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                                tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                            }
                        }
                    } else {
                        rglog.error("商户<{}> 结算账户类型<{}> 不是对公户也不是对私户，不能参加当前活动!", tmMcMchntFeeDiscountInfo.getMcNo(), settleAcctType);
                    }
                } else {
                    rglog.error("商户<{}> 结算账户信息查询异常，无法判断是否能够参与营销活动!", mcMchntFeeDiscountTxnData.getMchntNo());
                }
            }
        }
        rglog.info("判断各活动是否区分商户性质完成，流程继续！");
    }

    /**
     * 判断活动是否区分商户性质的才能参加--通用处理流程
     *
     * @author liujinan
     * @date 2021/5/12 10:13
     */
    private void JudgeMcDiscriminateMchntNatureOthers(List<TMMcMchntFeeDiscountInfo> inputTmMcMchntFeeDiscountInfo, List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) throws Exception {
        //当前商户号
        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();
        //当前商户的性质 01-小微商户 02-个体工商户 03-企业 04-党政 05-机关及事业单位 99-其他组织
        String mchntNature = mcMchntFeeDiscountTxnData.getMchntNature();
        rglog.info("当前商户<{}> 企业性质为<{}> 01-小微商户 02-个体工商户 03-企业 04-党政 05-机关及事业单位 99-其他组织", mchntNo, mchntNature);

        /* 判断活动是否区分商户性质参加，如果区分，则判断当前商户是否符合条件 */
        for (TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo : inputTmMcMchntFeeDiscountInfo) {
            //当前活动支持的商户类型
            String avySprtMrctTypString = tmMcMchntFeeDiscountInfo.getavySprtMrctTyp();
            if (null == avySprtMrctTypString ||
                    CommonConstant.EMPTY_STRING.equals(avySprtMrctTypString) ||
                    CommonConstant.SUPPORT_ALLTYPES_MCHNT.equals(avySprtMrctTypString)) {
                rglog.info("营销活动<{}> 支持所有类型的商户参加,无需校验当前商户的性质", tmMcMchntFeeDiscountInfo.getMcNo());
                tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
            } else {
                //当前活动支持的商户性质 小微商户|个体工商户|企业|党政|机关及事业单位|其他组织
                String[] avySprtMrctTyp = avySprtMrctTypString.split(CommonConstant.VERTICAL_LINE);

                if (CommonConstant.SIX != avySprtMrctTyp.length) {
                    rglog.error("营销活动<{}> 配置的支持参加的商户类型异常,商户无法参加本活动！", tmMcMchntFeeDiscountInfo.getMcNo());
                    continue;
                }

                switch (mchntNature) {
                    case "01":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[0])) {
                            rglog.info("营销活动<{}>限定商户性质,允许小微商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许小微商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "02":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[1])) {
                            rglog.info("营销活动<{}>限定商户性质,允许个体工商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许个体工商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "03":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[2])) {
                            rglog.info("营销活动<{}>限定商户性质,允许企业商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许企业商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "04":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[3])) {
                            rglog.info("营销活动<{}>限定商户性质,允许党政商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许党政商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "05":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[4])) {
                            rglog.info("营销活动<{}>限定商户性质,允许机关及事业单位商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许机关及事业单位商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "99":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[5])) {
                            rglog.info("营销活动<{}>限定商户性质,允许其他组织商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许其他组织商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    default:
                        rglog.error("当前活动<{}>限定商户性质，但当前商户的性质异常 mchntNature: <{}>", tmMcMchntFeeDiscountInfo.getMcNo(), mchntNature);
                        break;
                }
            }
        }
        rglog.info("判断各活动是否区分商户性质完成，流程继续！");
    }

    /**
     * 判断上送userId是否为json字符串，同时赋值
     *
     * @param userId
     * @return
     * @author pangjl
     * @date 2021.04.21
     */
    public boolean isJson(String userId) {
        try {
            JSONObject jsonObject = JSON.parseObject(userId);
            phoneNo = jsonObject.getString("phoneNo");
            cardNo = jsonObject.getString("cardNo");
            wechatId = jsonObject.getString("wechatId");
            alipayId = jsonObject.getString("alipayId");
            coreComId = jsonObject.getString("coreComId");
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 根据法人机构号 活动编号查询营销用户列表
     *
     * @param instId
     * @param mcNo
     * @return
     * @throws Exception
     * @author pangjl
     * @date 2021.04.21
     */
    private List<TMMcUserInfo> selectMcUserList(String instId, String mcNo) throws Exception {

        McUserInfoMapper mcUserInfoMapper = new McUserInfoMapperImpl();

        return mcUserInfoMapper.selectMcUserInfoList(instId, mcNo);
    }

    /**
     * 使用商户号和商户所在商圈编号和活动号匹配营销活动商户信息表中数据
     *
     * @param mchntBaseInfo 商户基本信息表T_B_MCHNT_BASE_INFO
     * @return java.util.List<cc.rengu.igas.momp.common.entity.TMMcMchntInfo> 营销活动商户信息表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/13 15:10
     */
    private List<TMMcMchntInfo> matchMcMchntInfoByUsingMchntInfoAndMcNo(TBMchntBaseInfo mchntBaseInfo, String mcNo) throws Exception {

        McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
        return mcMchntInfoMapper.matchMoMcInfoByMchntNoAndMchntAreaAndMcNo(mchntBaseInfo, mcNo);
    }

    /**
     * 校验商户是否重复入网商户
     *
     * @param mchntNo         商户编号
     * @param mchntExpandTime 商户入驻时间
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/5/28 09:06
     */
    private boolean checkMchntRepeatFlag(String mchntNo, String mchntExpandTime) throws Exception {
        boolean repeatFlag = false;
        /* 东营行校验重复入网 */
        if (INST_ID_DY.equals(globalInstId)) {
            rglog.info("根据机构号<{}>商户<{}>入驻时间<{}>校验是否存在注销后一年内重复入网商户", globalInstId, mchntNo, mchntExpandTime);
            //格式化商户入驻日期
            String mchntExpandDate = mchntExpandTime.replaceAll("-", "").substring(0, 8);
            //获取一年前日期
            String lastYearDate = MompDateUtil.getFutureMonDay(mchntExpandDate, -12);
            //获取商户基本信息,可能存在多个结算账号
            List<TBMchntSignInfo> tbMchntSignList = selectMchntSignInfoByPrimaryPK(globalInstId, mchntNo);
            rglog.info("查询商户<{}>签约信息size=<{}>", mchntNo, tbMchntSignList.size());
            for (TBMchntSignInfo tbMchntSignInfo : tbMchntSignList) {
                //查询历史签约商户号
                List<TBMchntSignInfo> signList = selectRepeatMchntBySignInfoForDY(globalInstId, mchntNo, tbMchntSignInfo.getArtifCertNo(), tbMchntSignInfo.getLicenceCode(), tbMchntSignInfo.getSettleAcctNo());
                if (signList != null && !signList.isEmpty()) {
                    rglog.info("查询商户<{}>证件信息历史入驻信息size=<{}>", mchntNo, signList.size());
                    for (TBMchntSignInfo signInfo : signList) {
                        String cancelMchntNo = signInfo.getMchntNo();
                        if (!cancelMchntNo.equals(mchntNo)) {
                            String expandTime = signInfo.getExpandTime();
                            String lastAuditTime = signInfo.getLastAuditTime();
                            rglog.info("商户<{}>入驻时间(一年前)<{}>,检查注销商户[{}],入驻时间为[{}],注销时间为[{}],", mchntNo, lastYearDate, cancelMchntNo, expandTime, lastAuditTime);
                            if (!StringUtil.isNullorEmpty(lastAuditTime)) {
                                //格式化商户注销日期
                                String cancelDate = DateUtil.dateStringFormatConvert(lastAuditTime.substring(0, 10), "yyyy-MM-dd", "yyyyMMdd");
                                //判断注销商户注销后是否一年内入网
                                if (DateUtil.compareDate(cancelDate, lastYearDate) > 0) {
                                    //查询商户营销统计商户表累计优惠额度
                                    TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeTotalAmtMchntStatistics(globalInstId, cancelMchntNo);
                                    if (tmStatMfdMchnt != null) {
                                        String totalAmtAcc = tmStatMfdMchnt.getTotalAmtAcc();
                                        //超过额度，判定为重复入网
                                        if (!StringUtil.isNullorEmpty(totalAmtAcc) && AmountUtil.compare(totalAmtAcc, DISCOUNT_AMOUNT) == 1) {
                                            repeatFlag = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return repeatFlag;
    }

    /**
     * 使用商户编号从内管商户签约信息表查询商户签约信息
     *
     * @param globalInstId 法人机构号
     * @param mchntNo      商户编号
     * @return cc.rengu.igas.momp.common.entity.TBMchntBaseInfo 商户基本信息表T_B_MCHNT_BASE_INFO
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2021/5/28 09:06
     */
    private List<TBMchntSignInfo> selectMchntSignInfoByPrimaryPK(String globalInstId, String mchntNo) throws Exception {
        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        return mchntInfoMapper.selectMchntSignInfoByPrimaryPK(globalInstId, mchntNo);
    }

    /**
     * 东营行商户重复入驻校验
     *
     * @param instId       成员行号
     * @param mchntNo      商户编号
     * @param artifCertNo  证件号码
     * @param licenceCode  营业执照
     * @param settleAcctNo 结算账户
     * @return
     * @throws Exception
     */
    private List<TBMchntSignInfo> selectRepeatMchntBySignInfoForDY(String instId, String mchntNo, String artifCertNo, String licenceCode, String settleAcctNo) throws Exception {
        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        return mchntInfoMapper.selectRepeatMchntBySignInfo(instId, mchntNo, artifCertNo, licenceCode, settleAcctNo);
    }

    /**
     * 使用主键查询手续费减免活动商户统计表累计优惠金额数据库操作接口实现
     *
     * @param instId  法人机构号
     * @param mchntNo 商户编号
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt 手续费减免活动商户统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2021/5/28 14:55
     */
    private TMStatMfdMchnt selectMchntFeeTotalAmtMchntStatistics(String instId, String mchntNo) throws Exception {
        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectMchntFeeTotalAmtMchntStatistics(instId, mchntNo);
    }

    /**
     * 重新计算手续费
     *
     * @return int 返回码
     * @author liujinan
     * @since 2021/5/19 09:36
     */
    private boolean recalculateMchntFee(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData, BigDecimal orderAmt, BigDecimal remainderDiscountAmt, String newMchntFeeFlag) throws Exception {
        String instId = mcMchntFeeDiscountTxnData.getInstId();
        String mchntNo = mcMchntFeeDiscountTxnData.getMchntNo();
        String feeType = mcMchntFeeDiscountTxnData.getFeeType();
        //不可优惠交易金额
        BigDecimal noDiscountAmt = orderAmt.subtract(remainderDiscountAmt);
        rglog.info("商户<{}> 订单总金额<{}> 可优惠交易金额<{}> 不可优惠交易金额<{}>", mchntNo, orderAmt, remainderDiscountAmt, noDiscountAmt);

        String calMchntFeeBizeProdCode = mcMchntFeeDiscountTxnData.getCalMchntFeeBizProdCode();
        //---计算不可优惠金额实际应该收的手续费
        if (null == feeType || null == calMchntFeeBizeProdCode) {
            rglog.error("商户<{}> 存在免充值的对客营销活动，营销需要重新计算手续费信息，费率类型和计算手续费产品编码必须上送！", mchntNo);
            throw new BizException(RespCodeEnum.REQUEST_PARAMETER_LOST.getRespCode(), RespCodeEnum.REQUEST_PARAMETER_LOST.getRespDesc());
        }

        CalcMchntFeeResultBean calcMchntFeeResultBean;
        CalcMchntFee calcMchntFee = new CalcMchntFee();
        try {
            CalcMchntFeeBean calcMchntFeeBean = new CalcMchntFeeBean();
            calcMchntFeeBean.setInstId(instId);
            calcMchntFeeBean.setMchntNo(mchntNo);
            calcMchntFeeBean.setTransAmt(noDiscountAmt.toString());
            calcMchntFeeBean.setIgasBizProdType(calMchntFeeBizeProdCode);
            calcMchntFeeBean.setSubProdType(feeType);
            calcMchntFeeBean.setStageCode("");
            calcMchntFeeBean.setStageNum("");
            calcMchntFeeResultBean = calcMchntFee.calcPayFee(calcMchntFeeBean);
            if (null == calcMchntFeeResultBean) {
                rglog.error("计算商户手续费失败,instId:<{}>,mchntNo:<{}>,transAmt:<{}>", instId, mchntNo, noDiscountAmt.toString());
                return false;
            }
        } catch (Exception e) {
            rglog.error("商户<{}> 计算不可优惠交易金额应收手续费失败 <{}>！！！", mchntNo, e);
            return false;
        }
        //不可优惠金额应收的手续费
        String noDiscountAmtMchntFee = calcMchntFeeResultBean.getMchntFee();
        rglog.info("商户<{}> 不可优惠交易金额应收手续费为<{}> ", mchntNo, noDiscountAmtMchntFee);
        if (null != noDiscountAmtMchntFee) {
            //判断不可优惠金额应收手续费和原所有订单金额优惠手续费相同，则无需重新计算剩余可优惠金额优惠的手续费
            if (new BigDecimal(noDiscountAmtMchntFee).compareTo(new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivable())) >= 0) {

                //剩余不可优惠金额应收手续费大于等于原总金额应收手续费，本笔交易实际无优惠手续费，只消耗优惠交易金额
                mcMchntFeeDiscountTxnData.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT);
                mcMchntFeeDiscountTxnData.setMchntFeeActual(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
            } else {
                //--剩余不可优惠金额应收手续费小于原总金额应收手续费，计算可优惠金额应收手续费，优惠手续费
                CalcMchntFeeResultBean calcDiscountMchntFeeResultBean;
                try {
                    CalcMchntFeeBean calcDiscountMchntFeeBean = new CalcMchntFeeBean();
                    calcDiscountMchntFeeBean.setInstId(instId);
                    calcDiscountMchntFeeBean.setMchntNo(mchntNo);
                    calcDiscountMchntFeeBean.setTransAmt(remainderDiscountAmt.toString());
                    calcDiscountMchntFeeBean.setIgasBizProdType(calMchntFeeBizeProdCode);
                    calcDiscountMchntFeeBean.setSubProdType(feeType);
                    calcDiscountMchntFeeBean.setStageCode("");
                    calcDiscountMchntFeeBean.setStageNum("");
                    calcDiscountMchntFeeResultBean = calcMchntFee.calcPayFee(calcDiscountMchntFeeBean);
                    if (null == calcDiscountMchntFeeResultBean) {
                        rglog.error("计算商户优惠手续费失败,instId:<{}>,mchntNo:<{}>,transAmt:<{}>", instId, mchntNo, remainderDiscountAmt.toString());
                        return false;
                    }
                } catch (Exception e) {
                    rglog.error("商户<{}> 计算可优惠交易金额应收手续费失败 <{}>！！！", mchntNo, e);
                    return false;
                }

                //可优惠金额应收的手续费
                String discountAmtMchntFee = calcDiscountMchntFeeResultBean.getMchntFee();
                rglog.info("商户<{}> 可优惠交易金额应收手续费为<{}> ", mchntNo, discountAmtMchntFee);

                //如果可优惠金额应收的手续费为0，所以实际可优惠的金额是无需收取手续费的
                if (BigDecimal.ZERO.compareTo(new BigDecimal(discountAmtMchntFee)) == 0
                        && BigDecimal.ZERO.compareTo(new BigDecimal(noDiscountAmtMchntFee)) == 0) {
                    rglog.info("剩余可优惠的交易金额及剩余不可优惠金额应收手续费均为0");
                    mcMchntFeeDiscountTxnData.setMchntFeeDiscount(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
                    mcMchntFeeDiscountTxnData.setMchntFeeActual(CommonConstant.ZERO_AMOUNT);
                } else if (BigDecimal.ZERO.compareTo(new BigDecimal(discountAmtMchntFee)) == 0) {
                    rglog.info("剩余可优惠的交易金额应收手续费为0");
                    mcMchntFeeDiscountTxnData.setMchntFeeDiscount(new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivable()).subtract(new BigDecimal(noDiscountAmtMchntFee)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
                    mcMchntFeeDiscountTxnData.setMchntFeeActual(noDiscountAmtMchntFee);
                } else {
                    rglog.info("剩余可优惠的交易金额应收手续费不为0");

                    //如果是新商户，则可优惠金额直接免手续费，不需要通过规则计算优惠的手续费
                    if (CommonConstant.ONE_COMMON_CONSTANT.equals(newMchntFeeFlag)) {
                        rglog.info("商户<{}> 为新商户，剩余可优惠的交易金额直接免手续费，无需通过规则计算优惠值 ", mchntNo);
                        mcMchntFeeDiscountTxnData.setMchntFeeDiscount(discountAmtMchntFee);
                        //计算实收的手续费
                        BigDecimal mchntFeeActual = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivable()).subtract(new BigDecimal(discountAmtMchntFee)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        mcMchntFeeDiscountTxnData.setMchntFeeActual(mchntFeeActual.toString());
                    } else {
                        //存量商户获取计算规则，计算可优惠金额能够优惠的手续费
                        McMchntFeeDiscountTxnData discountmcMchntFeeDiscountTxnData = new McMchntFeeDiscountTxnData();
                        discountmcMchntFeeDiscountTxnData.setDiscountType(mcMchntFeeDiscountTxnData.getDiscountType());
                        discountmcMchntFeeDiscountTxnData.setMchntNo(mchntNo);
                        discountmcMchntFeeDiscountTxnData.setMchntFeeReceivable(discountAmtMchntFee);
                        discountmcMchntFeeDiscountTxnData.setMchntFeeReceivableRate(mcMchntFeeDiscountTxnData.getMchntFeeReceivableRate());
                        discountmcMchntFeeDiscountTxnData.setDiscount(mcMchntFeeDiscountTxnData.getDiscount());
                        discountmcMchntFeeDiscountTxnData.setFeeInputMode(mcMchntFeeDiscountTxnData.getFeeInputMode());
                        discountmcMchntFeeDiscountTxnData.setOrderAmt(remainderDiscountAmt.toString());

                        //根据营销活动规则计算可优惠金额的补贴减免金额
                        String subsidy = calculateMchntFeeDiscountSubsidy(discountmcMchntFeeDiscountTxnData);
                        if (null == subsidy) {
                            rglog.info("商户<{}> 剩余可优惠的交易金额计算手续费优惠金额异常!", mchntNo);
                            return false;
                        } else {
                            BigDecimal zeroAmt = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            BigDecimal totalSubsidy = new BigDecimal(discountmcMchntFeeDiscountTxnData.getMchntFeeDiscount()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            if (CommonConstant.ZERO == zeroAmt.compareTo(totalSubsidy)) {
                                /* 优惠金额为0,不优惠商户手续费 */
                                rglog.info("通过计算商户<{}> 剩余可优惠交易金额的优惠手续费为0,不优惠,这种情况也消耗优惠交易金额!", mchntNo);
                                //剩余可优惠的交易金额没有优惠，本笔交易总体没有手续费优惠 ，只消耗优惠交易金额
                                mcMchntFeeDiscountTxnData.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT);
                                mcMchntFeeDiscountTxnData.setMchntFeeActual(mcMchntFeeDiscountTxnData.getMchntFeeReceivable());
                            } else {
                                rglog.info("商户<{}> 可优惠交易金额的的手续费减免金额<{}>", mchntNo, totalSubsidy);
                                mcMchntFeeDiscountTxnData.setMchntFeeDiscount(totalSubsidy.toString());
                                //计算实收的手续费
                                BigDecimal mchntFeeActual = new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeReceivable()).subtract(new BigDecimal(discountmcMchntFeeDiscountTxnData.getMchntFeeDiscount())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                                mcMchntFeeDiscountTxnData.setMchntFeeActual(mchntFeeActual.toString());
                            }
                        }
                    }
                }
            }
        } else {
            rglog.error("商户<{}> 计算不可优惠交易金额应收手续费，返回手续费错误", mchntNo);
            return false;
        }
        return true;
    }

    /**
     * 使用主键查询统计信息备份表最新一条数据
     *
     * @param instId
     * @param statType
     * @param statPrimaryKey
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod
     * @throws Exception
     * @author liujinan
     * @date 2021/7/9
     */
    private TMStatBak selectTMStatBakByStatPrimaryKey(String instId, String statType, String statPrimaryKey) throws Exception {

        TMStatBakMapper tmStatBakMapper = new TMStatBakMapperImpl();
        return tmStatBakMapper.selectTMStatBakByStatPrimaryKey(instId, statType, statPrimaryKey);
    }

    /**
     * 手续费减免活动周期统计数据赋值
     *
     * @param tmStatMfdPeriod 手续费减免活动周期统计表
     * @param tmStatMfdDay    手续费减免活动单日统计表
     * @author liujinan
     * @since 2021/7/12 11:23
     */
    private void copyMchntFeeDiscountMchntStatData(TMStatMfdPeriod tmStatMfdPeriod, TMStatMfdDay tmStatMfdDay) {

        /* 手续费减免活动周期统计表-累计优惠笔数 */
        tmStatMfdPeriod.setTotalQtyAcc(new BigDecimal(tmStatMfdPeriod.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTotalQtyAcc())).toString());
        /* 手续费减免活动周期统计表-累计优惠金额 */
        tmStatMfdPeriod.setTotalAmtAcc(new BigDecimal(tmStatMfdPeriod.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());
        /* 手续费减免活动周期统计表-累计交易笔数 */
        tmStatMfdPeriod.setTxnQtyAcc(new BigDecimal(tmStatMfdPeriod.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTxnQtyAcc())).toString());
        /* 手续费减免活动周期统计表-累计交易金额 */
        tmStatMfdPeriod.setTxnAmtAcc(new BigDecimal(tmStatMfdPeriod.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTxnAmtAcc())).toString());
    }

    /**
     * 手续费减免活动周期统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfdPeriod 手续费减免活动周期统计表
     * @param tmStatMfdDay    手续费减免活动周期统计表
     * @author liujinan
     * @since 2021/7/12 11:22
     */
    private void copyMchntFeeDiscountPeriodZeroStatData(TMStatMfdPeriod tmStatMfdPeriod, TMStatMfdDay tmStatMfdDay, McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) {
        BigDecimal thisOrderTotalAmtAcc = BigDecimal.ZERO;
        List<TMStatMfdDay> statMfdThisOrderList = statMfdDayList.stream().filter(item -> item.getInstId().equals(mcMchntFeeDiscountTxnData.getInstId()) && item.getMcNo().equals(mcMchntFeeDiscountTxnData.getMcNo())).collect(Collectors.toList());
        if (statMfdThisOrderList.size() > 0) {
            //本笔流水中交易额,包含本笔明细中的
            TMStatMfdDay statMfdThisOrder = statMfdThisOrderList.get(0);
            thisOrderTotalAmtAcc = new BigDecimal(statMfdThisOrder.getTotalAmtAcc());
        }

        /* 手续费减免活动周期统计数据-周期内消耗金额 加本订单中参加相同活动的商户消耗预算，不加本明细手续费*/
        mcMchntFeeDiscountTxnData.setPeriodTotalAmtAcc(new BigDecimal(tmStatMfdPeriod.getTotalAmtAcc()).
                add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).
                add(thisOrderTotalAmtAcc).
                subtract(new BigDecimal(mcMchntFeeDiscountTxnData.getMchntFeeDiscount())).toString());
    }

    /**
     * 检查营销活动状态
     * 商户手续费优惠类营销活动同时检查新增商户对应的当前交易日期是否在营销活动时间范围内
     *
     * @param mcMchntFeeDiscountTxnData 数据入参对象
     * @return int 返回码
     * @author liujinan
     * @since 2021/7/15 10:00
     */
    private int checkNewMchntMcStatus(McMchntFeeDiscountTxnData mcMchntFeeDiscountTxnData) {

        /* 商户手续费优惠类营销活动 */
        String instId = mcMchntFeeDiscountTxnData.getInstId();
        String mcStatus = mcMchntFeeDiscountTxnData.getMcStatus();
        String mcNo = mcMchntFeeDiscountTxnData.getMcNo();

        /* 判断营销活动状态是否是进行中  商户已判断是否在优惠周期内  checkNewMchntAvailability方法*/
        if (McStatusEnum.PROGRESSING.getMcStatusCode().equals(mcStatus)) {
            rglog.info("活动状态为进行中，新商户给予优惠, INST_ID=<{}>, MC_NO=<{}>, MC_STATUS=<{}>", instId, mcNo, mcStatus);
            return CommonConstant.PROCESS_SUCCESS;
        } else if (McStatusEnum.ENDED.getMcStatusCode().equals(mcStatus)) {
            rglog.info("活动状态为自然结束，已判断活动是否支持顺延并且商户还在优惠周期内，新商户给予优惠, INST_ID=<{}>, MC_NO=<{}>, MC_STATUS=<{}>", instId, mcNo, mcStatus);
            return CommonConstant.PROCESS_SUCCESS;
        } else {
            rglog.info("活动状态为暂停或强制终止或其他状态，新商户不给予优惠, INST_ID=<{}>, MC_NO=<{}>, MC_STATUS=<{}>", instId, mcNo, mcStatus);
            return CommonConstant.PROCESS_FAILED;
        }
    }

    /**
     * 潍坊行新平台营销规则检查
     *
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/6/21 14:40
     */
    private boolean checkPrkAvyRule(TMMcMoneyOffInfo tmMcMoneyOffInfo) throws Exception {
        rglog.info("根据机构号<{}>活动号<{}>查询卡产品信息", globalInstId, tmMcMoneyOffInfo.getMcNo());
        McUserInfoMapper mcUserInfoMapper = new McUserInfoMapperImpl();
        List<TMMcUserInfo> userInfoList = mcUserInfoMapper.selectMcUserInfoList(globalInstId, tmMcMoneyOffInfo.getMcNo());
        if (null == userInfoList) {
            rglog.info("未查询到卡产品信息");
        } else {
            rglog.info("查询到卡产品信息<{}>条", userInfoList.size());
        }
        TPSignAcctInfoMapper tpSignAcctInfoMapper = new TPSignAcctInfoMapperImpl();
        rglog.info("根据卡号<{}>查询用户签约信息", discountId);
        TPSignAcctInfo tpSignAcctInfo = new TPSignAcctInfo();
        tpSignAcctInfo.setInstId(globalInstId);
        //70 无感支付
        tpSignAcctInfo.setSignTokenType("70");
        tpSignAcctInfo.setSignAcctNo(discountId);
        TPSignAcctInfo tpSignAcctInfos = tpSignAcctInfoMapper.selectSignAcctByInstIdTokenTypeAcctNo(tpSignAcctInfo);
        if (null == tpSignAcctInfos) {
            rglog.info("根据卡号<{}>查询用户签约信息失败", discountId);
            return false;
        }
        //身份证号
        String certNo = tpSignAcctInfos.getCertNo();
        tpSignAcctInfo = new TPSignAcctInfo();
        tpSignAcctInfo.setInstId(globalInstId);
        //70 无感支付
        tpSignAcctInfo.setSignTokenType("70");
        tpSignAcctInfo.setCertNo(certNo);
        List<TPSignAcctInfo> tpSignAcctInfoList = tpSignAcctInfoMapper.selectSignAcctByInstIdUserIdTokenTypeCertNo(tpSignAcctInfo);
        if (null == tpSignAcctInfoList || tpSignAcctInfoList.isEmpty()) {
            rglog.info("根据身份证号<{}>查询用户签约信息失败", certNo);
            return false;
        }
        //普卡优惠次数
        int restriction = 0;
        //用户下所有卡参与次数
        int totalQtyAcc = 0;
        if (tmMcMoneyOffInfo.getClientRange().equals(CommonConstant.SPECIFIC_CLIENT_SUPPORT)) {
            rglog.info("活动为卡维度活动，区分车主卡普卡优惠次数，分别按照普卡优惠次数和车主卡优惠次数限制");
            //车主卡
            List<TPSignAcctInfo> ownerCardList = new ArrayList<>();
            //普卡
            List<TPSignAcctInfo> ordinaryCardList = tpSignAcctInfoList;
            for (TMMcUserInfo tmMcUserInfo : userInfoList) {
                ownerCardList.addAll(tpSignAcctInfoList.stream().filter(item -> item.getSignAcctNo().substring(0, 10).equals(tmMcUserInfo.getAcctNo())).collect(Collectors.toList()));
                ordinaryCardList = ordinaryCardList.stream().filter(item -> !item.getSignAcctNo().substring(0, 10).equals(tmMcUserInfo.getAcctNo())).collect(Collectors.toList());
            }
            //去重
            ordinaryCardList = ordinaryCardList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(TPSignAcctInfo::getSignAcctNo))), ArrayList::new));
            rglog.info("获取到用户身份证下<{}>车主卡<{}>普卡<{}>", certNo, ownerCardList.size(), ordinaryCardList.size());
            //用户下所有卡今日参与次数
            int todayQtyAcc = 0;
            //用户下所有卡本周参与次数
            int weekQtyAcc = 0;
            //用户下所有卡本月参与次数
            int monthQtyAcc = 0;
            //用户下所有卡本季度参与次数
            int querterQtyAcc = 0;
            //用户下所有卡本年参与次数
            int yearQtyAcc = 0;
            //车主卡规则
            TMMcUserInfo tmMcUserInfo = new TMMcUserInfo();
            //0 车主卡 1 普卡
            int flag;
            if (ordinaryCardList.stream().filter(item -> item.getSignAcctNo().equals(discountId)).collect(Collectors.toList()).size() > 0) {
                restriction = Integer.parseInt(tmMcMoneyOffInfo.getOdcrdDisTimes());
                flag = CommonConstant.FLAG_SET;
                rglog.info("交易上送卡号为普卡，按照普卡优惠次数限额<{}>", restriction);
            } else {
                if (ownerCardList.stream().filter(item -> item.getSignAcctNo().equals(discountId)).collect(Collectors.toList()).size() > 0) {
                    tmMcUserInfo = userInfoList.stream().filter(item -> item.getAcctNo().equals(discountId.substring(0, 10))).collect(Collectors.toList()).get(0);
                    flag = CommonConstant.FLAG_NOT_SET;
                    restriction = Integer.parseInt(tmMcUserInfo.getRestriction());
                    rglog.info("交易上送卡号为车主卡，按照车主卡优惠次数限额，卡bin<{}>", tmMcUserInfo.getAcctNo());
                    ownerCardList = ownerCardList.stream().filter(item -> item.getSignAcctNo().substring(0, 10).equals(discountId.substring(0, 10))).collect(Collectors.toList());
                    rglog.info("与上送卡号同卡bin<{}>的车主卡，用户<{}>一共有<{}>张", discountId.substring(0, 10), certNo, ownerCardList.size());
                } else {
                    rglog.info("活动卡bin规则配置异常");
                    return false;
                }
            }
            rglog.info("获取身份证号<{}>下卡号参与营销活动次数", certNo);
            if (flag == CommonConstant.FLAG_NOT_SET) {
                //获取用户下所有车主卡已使用的次数
                for (TPSignAcctInfo newTpSignAcctInfo : ownerCardList) {
                    TMStat2CUserDayTransCount tmStat2CUserDayTransCount = getUserAttendMcCountDay(globalTxnDate, newTpSignAcctInfo.getSignAcctNo(), tmMcMoneyOffInfo.getMcNo());
                    tmStat2CUserDayTransCount.setMcStartDate(tmMcMoneyOffInfo.getMcStartDate());
                    tmStat2CUserDayTransCount.setMcType(tmMcMoneyOffInfo.getMcType());
                    int cardQtyAcc = selectUserCardQtyAcc(tmMcMoneyOffInfo.getMcNo(), tmStat2CUserDayTransCount);
                    if (cardQtyAcc == CommonConstant.MINUS_ONE) {
                        rglog.info("获取卡号<{}>用户统计表数据异常", newTpSignAcctInfo.getSignAcctNo());
                        return false;
                    } else {
                        totalQtyAcc = totalQtyAcc + cardQtyAcc;
                    }
                    //每日优惠次数需要限制
                    if (null != tmMcUserInfo.getDayRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getDayRestriction())) {
                        todayQtyAcc = todayQtyAcc + tmStat2CUserDayTransCount.getDayPaymentCount();

                    }

                    //每周优惠次数需要限制
                    if (null != tmMcUserInfo.getWeekRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getWeekRestriction())) {
                        weekQtyAcc = weekQtyAcc + obtainUserMcLimit(tmStat2CUserDayTransCount, tmMcMoneyOffInfo.getMcNo(), "week");
                    }

                    //每月优惠次数需要限制
                    if (null != tmMcUserInfo.getMonthRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getMonthRestriction())) {
                        monthQtyAcc = monthQtyAcc + obtainUserMcLimit(tmStat2CUserDayTransCount, tmMcMoneyOffInfo.getMcNo(), "month");
                    }

                    //每季度优惠次数需要限制
                    if (null != tmMcUserInfo.getQuerterRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getQuerterRestriction())) {
                        querterQtyAcc = querterQtyAcc + obtainUserMcLimit(tmStat2CUserDayTransCount, tmMcMoneyOffInfo.getMcNo(), "querter");
                    }

                    //每年优惠次数需要限制
                    if (null != tmMcUserInfo.getYearRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getYearRestriction())) {
                        yearQtyAcc = yearQtyAcc + obtainUserMcLimit(tmStat2CUserDayTransCount, tmMcMoneyOffInfo.getMcNo(), "year");
                    }
                }
                rglog.info("判断车主卡是否有日周月季年次数限制");
                //每日优惠次数需要限制
                if (null != tmMcUserInfo.getDayRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getDayRestriction())) {
                    rglog.info("车主卡存在每日次数限制");
                    if (todayQtyAcc >= Integer.parseInt(tmMcUserInfo.getDayRestriction())) {
                        rglog.info("用户下所有卡号已参与次数<{}>大于等于本日优惠次数限制<{}>，本次不予优惠", todayQtyAcc, tmMcUserInfo.getDayRestriction());
                        return false;
                    }
                }
                //每周优惠次数需要限制
                if (null != tmMcUserInfo.getWeekRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getWeekRestriction())) {
                    rglog.info("车主卡存在每周次数限制");
                    if (weekQtyAcc >= Integer.parseInt(tmMcUserInfo.getWeekRestriction())) {
                        rglog.info("用户下所有卡号已参与次数<{}>大于等于本周优惠次数限制<{}>，本次不予优惠", weekQtyAcc, tmMcUserInfo.getWeekRestriction());
                        return false;
                    }
                }

                //每月优惠次数需要限制
                if (null != tmMcUserInfo.getMonthRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getMonthRestriction())) {
                    rglog.info("车主卡存在每月次数限制");
                    if (monthQtyAcc >= Integer.parseInt(tmMcUserInfo.getMonthRestriction())) {
                        rglog.info("用户下所有卡号已参与次数<{}>大于等于本月优惠次数限制<{}>，本次不予优惠", monthQtyAcc, tmMcUserInfo.getMonthRestriction());
                        return false;
                    }
                }

                //每季度优惠次数需要限制
                if (null != tmMcUserInfo.getQuerterRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getQuerterRestriction())) {
                    rglog.info("车主卡存在每季度次数限制");
                    if (querterQtyAcc >= Integer.parseInt(tmMcUserInfo.getQuerterRestriction())) {
                        rglog.info("用户下所有卡号已参与次数<{}>大于等于本季优惠次数限制<{}>，本次不予优惠", querterQtyAcc, tmMcUserInfo.getQuerterRestriction());
                        return false;
                    }
                }

                //每年优惠次数需要限制
                if (null != tmMcUserInfo.getYearRestriction() && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getYearRestriction())) {
                    rglog.info("车主卡存在每年次数限制");
                    if (yearQtyAcc >= Integer.parseInt(tmMcUserInfo.getYearRestriction())) {
                        rglog.info("用户下所有卡号已参与次数<{}>大于等于本年优惠次数限制<{}>，本次不予优惠", yearQtyAcc, tmMcUserInfo.getYearRestriction());
                        return false;
                    }
                }
                if (totalQtyAcc >= restriction) {
                    rglog.info("用户下所属卡产品<{}>下所有车主卡已参与次数<{}>大于等于同类型车主卡优惠次数<{}>，本次不予优惠", tmMcUserInfo.getAcctNo(), totalQtyAcc, restriction);
                    return false;
                } else {
                    rglog.info("用户下所属卡产品<{}>下所有车主卡已参与次数<{}>小于同类型车主卡优惠次数<{}>，本次给予优惠", tmMcUserInfo.getAcctNo(), totalQtyAcc, restriction);
                    return true;
                }

            } else {
                //获取用户下所有普卡已经使用的优惠次数
                for (TPSignAcctInfo newTpSignAcctInfo : ordinaryCardList) {
                    TMStat2CUserDayTransCount tmStat2CUserDayTransCount = getUserAttendMcCountDay(globalTxnDate, newTpSignAcctInfo.getSignAcctNo(), tmMcMoneyOffInfo.getMcNo());
                    tmStat2CUserDayTransCount.setMcType(tmMcMoneyOffInfo.getMcType());
                    tmStat2CUserDayTransCount.setMcStartDate(tmMcMoneyOffInfo.getMcStartDate());
                    int cardQtyAcc = selectUserCardQtyAcc(tmMcMoneyOffInfo.getMcNo(), tmStat2CUserDayTransCount);
                    if (cardQtyAcc == CommonConstant.MINUS_ONE) {
                        rglog.info("获取卡号<{}>用户统计表数据异常", newTpSignAcctInfo.getSignAcctNo());
                        return false;
                    } else {
                        totalQtyAcc = totalQtyAcc + cardQtyAcc;
                    }
                }
                if (totalQtyAcc >= restriction) {
                    rglog.info("用户下所有普卡已参与次数<{}>大于等于优惠次数<{}>，本次不予优惠", totalQtyAcc, restriction);
                    return false;
                } else {
                    rglog.info("用户下所有普卡已参与次数<{}>小于优惠次数<{}>，本次给予优惠", totalQtyAcc, restriction);
                    return true;
                }
            }
        } else {
            rglog.info("活动为客户维度，不区分普卡车主卡次数，按照活动设置次数限制优惠");
            restriction = Integer.parseInt(tmMcMoneyOffInfo.getRestriction());
            for (TPSignAcctInfo newTpSignAcctInfo : tpSignAcctInfoList) {
                TMStat2CUserDayTransCount tmStat2CUserDayTransCount = getUserAttendMcCountDay(globalTxnDate, newTpSignAcctInfo.getSignAcctNo(), tmMcMoneyOffInfo.getMcNo());
                tmStat2CUserDayTransCount.setMcType(tmMcMoneyOffInfo.getMcType());
                tmStat2CUserDayTransCount.setMcStartDate(tmMcMoneyOffInfo.getMcStartDate());
                int cardQtyAcc = selectUserCardQtyAcc(tmMcMoneyOffInfo.getMcNo(), tmStat2CUserDayTransCount);
                if (cardQtyAcc == CommonConstant.MINUS_ONE) {
                    rglog.info("获取卡号<{}>用户统计表数据异常", newTpSignAcctInfo.getSignAcctNo());
                    return false;
                } else {
                    totalQtyAcc = totalQtyAcc + cardQtyAcc;
                }
            }
            if (totalQtyAcc >= restriction) {
                rglog.info("用户下所有车主卡/普卡已参与次数<{}>大于等于优惠次数<{}>，本次不予优惠", totalQtyAcc, restriction);
                return false;
            } else {
                rglog.info("用户下所有车主卡/普卡已参与次数<{}>小于优惠次数<{}>，本次给予优惠", totalQtyAcc, restriction);
                return true;
            }
        }
    }

    /**
     * 用户参与活动 日周月季年维度是否超限
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/11/13 23:40
     */
    private int obtainUserMcLimit(TMStat2CUserDayTransCount tmStat2CUserDayTransCount, String mcNo, String flag) throws Exception {
        String userId = tmStat2CUserDayTransCount.getUserId();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        int todayQtyAcc = tmStat2CUserDayTransCount.getDayPaymentCount();
        String mcType = tmStat2CUserDayTransCount.getMcType();
        String mcStartDate = tmStat2CUserDayTransCount.getMcStartDate();
        //活动开始月
        String mcMonth = mcStartDate.substring(0, 6);
        //当前月份
        String nowMonth = globalTxnDate.substring(0, 6);
        LocalDate inputDate = LocalDate.parse(globalTxnDate, DateTimeFormatter.BASIC_ISO_DATE);
        //上个月
        String lastMonth = MompDateUtil.getBaseDateOffsetMonth(nowMonth, -1);
        //上个月是否取前一天的数据
        int batchStatusStatLastMonth = CommonConstant.FLAG_NOT_SET;
        //累计优惠笔数
        int totalQtyAcc = 0;
        switch (flag) {
            case "week":
                LocalDate beginDayOfWeek = inputDate.with(DayOfWeek.MONDAY);
                String firstDayOfWeek = beginDayOfWeek.toString().replaceAll("-", "");

                //今天是周的第一天，则总优惠笔数即为今天发生的优惠笔数
                if (globalTxnDate.equals(firstDayOfWeek)) {
                    totalQtyAcc = todayQtyAcc;
                    return totalQtyAcc;
                } else {
                    int i = 0;
                    boolean isGetBeforeSecondData = false;
                    TMStat2CUserDay tmStat2CUserDay;

                    String date = firstDayOfWeek;
                    //今天不是周的第一天，则取前一天的数据，判断前一天是否有数据，如果没有则需要取昨天的前一天的数据
                    while (i < 6) {
                        i++;
                        if (globalTxnDate.equals(date)) {
                            //如果获取日期已经是今天了，则退出
                            break;
                        }

                        //当日的统计数据
                        tmStat2CUserDay = getToClientMcUserDayStatistics(mcNo, date, userId);
                        totalQtyAcc = totalQtyAcc + Integer.parseInt(tmStat2CUserDay.getTotalQtyAcc());

                        //判断当前获取的日统计数据为昨日的
                        if (lastDate.equals(date)) {
                            //当获取到的昨日单日统计数据为0时，则需要自己获取昨天的数据
                            if (CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStat2CUserDay.getTotalQtyAcc()))
                                isGetBeforeSecondData = true;
                        }

                        date = DateUtil.getBaseDateOffsetDay(date, 1);
                    }

                    if (isGetBeforeSecondData) {
                        //获取昨日统计数据
                        //获取的数据累加到活动统计中
                        TMStat2CUserDayTransCount tmStat2CUserDayTransCountLastDay = getUserAttendMcCountDay(lastDate, userId, mcNo);

                        totalQtyAcc = totalQtyAcc + tmStat2CUserDayTransCountLastDay.getDayPaymentCount() - tmStat2CUserDayTransCountLastDay.getWeekRefundCount();
                    }

                    //加上当日的统计值
                    totalQtyAcc = totalQtyAcc + todayQtyAcc - tmStat2CUserDayTransCount.getWeekRefundCount();
                    return totalQtyAcc;
                }
            case "month":

                TMStat2CUserMonth tmStat2CUserMonth = getToClientMcUserMonthStatistics(mcNo, nowMonth, mcType, mcStartDate, userId);

                if (null == tmStat2CUserMonth) {
                    rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}> 统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, nowMonth);
                    return CommonConstant.PROCESS_FAILED;
                }

                //累计优惠笔数
                totalQtyAcc = Integer.parseInt(tmStat2CUserMonth.getTotalQtyAcc());

                //活动统计的加当日统计的
                totalQtyAcc = totalQtyAcc + todayQtyAcc - tmStat2CUserDayTransCount.getMonthRefundCount();
                return totalQtyAcc;
            case "querter":
                Month months = inputDate.getMonth();
                Month firstMonthOfQuarter = months.firstMonthOfQuarter();
                LocalDate quarterFirstDay = LocalDate.of(inputDate.getYear(), firstMonthOfQuarter, 1);
                String firstDayOfQuarter = quarterFirstDay.toString().replaceAll("-", "");

                String quarterFirstMonth = firstDayOfQuarter.substring(0, 6);

                //获取月统计表数据
                //今天是季度的第一个月，则季度值为月统计表中本月的统计值
                if (nowMonth.equals(quarterFirstMonth)) {
                    TMStat2CUserMonth tmStat2CUserMonths = getToClientMcUserMonthStatistics(mcNo, nowMonth, mcType, mcStartDate, userId);

                    if (null == tmStat2CUserMonths) {
                        rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}> 统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, nowMonth);
                        return CommonConstant.PROCESS_FAILED;
                    }

                    //累计优惠笔数
                    totalQtyAcc = Integer.parseInt(tmStat2CUserMonths.getTotalQtyAcc());

                } else {
                    int i = 0;
                    String everyMonth = quarterFirstMonth;
                    //取当前季度每个月的统计值
                    while (i < 3) {
                        i++;
                        if (new BigDecimal(mcMonth).compareTo(new BigDecimal(everyMonth)) > 0) {
                            rglog.info("活动开始月<{}>大于查询月<{}>，跳过查询", mcMonth, everyMonth);
                            everyMonth = MompDateUtil.getBaseDateOffsetMonth(everyMonth, 1);
                            continue;
                        }
                        TMStat2CUserMonth tmStat2CUserMonths = getToClientMcUserMonthStatistics(mcNo, everyMonth, mcType, mcStartDate, userId);

                        if (null == tmStat2CUserMonths) {
                            rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}> 统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, everyMonth);
                            return CommonConstant.PROCESS_FAILED;
                        }

                        //累计优惠笔数
                        totalQtyAcc = totalQtyAcc + Integer.parseInt(tmStat2CUserMonths.getTotalQtyAcc());


                        //如果当前获取的月份统计值即为当前日期所在的月，则循环结束
                        if (nowMonth.equals(everyMonth))
                            break;

                        everyMonth = MompDateUtil.getBaseDateOffsetMonth(everyMonth, 1);
                    }
                }

                //活动统计的加当日统计的
                totalQtyAcc = totalQtyAcc + todayQtyAcc - tmStat2CUserDayTransCount.getQuerterRefundCount();
                return totalQtyAcc;
            case "year":
                //获取当前日期季度的第一天
                LocalDate quarterFirstDays = LocalDate.of(inputDate.getYear(), Month.JANUARY, 1);
                String firstDayOfQuarters = quarterFirstDays.toString().replaceAll("-", "");

                String yearFirstMonth = firstDayOfQuarters.substring(0, 6);

                //获取月统计表数据
                //今天在今年的第一个月，则年统计值为月统计表中本月的统计值
                if (nowMonth.equals(yearFirstMonth)) {
                    TMStat2CUserMonth tmStat2CUserMonths = getToClientMcUserMonthStatistics(mcNo, nowMonth, mcType, mcStartDate, userId);

                    if (null == tmStat2CUserMonths) {
                        rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}>统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, nowMonth);
                        return CommonConstant.PROCESS_FAILED;
                    }

                    //累计优惠笔数
                    totalQtyAcc = Integer.parseInt(tmStat2CUserMonths.getTotalQtyAcc());
                    return totalQtyAcc;

                } else {
                    int i = 0;
                    String everyMonth = yearFirstMonth;
                    //取当年每个月的统计值
                    while (i < 12) {
                        i++;
                        if (new BigDecimal(mcMonth).compareTo(new BigDecimal(everyMonth)) > 0) {
                            rglog.info("活动开始月<{}>大于查询月<{}>，跳过查询", mcMonth, everyMonth);
                            everyMonth = MompDateUtil.getBaseDateOffsetMonth(everyMonth, 1);
                            continue;
                        }
                        TMStat2CUserMonth tmStat2CUserMonths = getToClientMcUserMonthStatistics(mcNo, everyMonth, mcType, mcStartDate, userId);

                        if (null == tmStat2CUserMonths) {
                            rglog.error("机构<{}> 对客营销活动<{}> 用户<{}> 获取营销活动用户月份<{}>统计表数据异常，不可参与本活动!", globalInstId, mcNo, userId, everyMonth);
                            return CommonConstant.PROCESS_FAILED;
                        }

                        //累计优惠笔数
                        totalQtyAcc = totalQtyAcc + Integer.parseInt(tmStat2CUserMonths.getTotalQtyAcc());

                        //如果当前获取的月份统计值即为当前日期所在的月，则循环结束
                        if (nowMonth.equals(everyMonth))
                            break;

                        everyMonth = MompDateUtil.getBaseDateOffsetMonth(everyMonth, 1);
                    }
                }


                //活动统计的加当日统计的
                totalQtyAcc = totalQtyAcc + todayQtyAcc - tmStat2CUserDayTransCount.getYearRefundCount();
                return totalQtyAcc;
            default:
                rglog.error("错误的查询方式");
                return CommonConstant.PROCESS_FAILED;
        }
    }

    /**
     * 对客活动用户统计表赋值
     *
     * @param tmStat2CUser              对客活动统计表
     * @param tMStat2CUserDayTransCount 对客活动单日统计
     * @author liujinan
     * @since 2021/7/12 11:23
     */
    private void copytmStat2CUserData(TMStat2CUser tmStat2CUser, TMStat2CUserDayTransCount tMStat2CUserDayTransCount) {

        /* 对客活动统计表-累计优惠笔数 */
        tmStat2CUser.setTotalQtyAcc(new BigDecimal(tmStat2CUser.getTotalQtyAcc()).add(new BigDecimal(tMStat2CUserDayTransCount.getDayPaymentCount())).subtract(new BigDecimal(tMStat2CUserDayTransCount.getDayRefundCount())).toString());
    }

    /**
     * 对客活动用户月统计表数据赋值
     *
     * @param tmStat2CUserMonth         对客活动月统计表
     * @param tMStat2CUserDayTransCount 对客活动单日统计
     * @author liujinan
     * @since 2021/7/12 11:23
     */
    private void copytmStat2CUserMonthData(TMStat2CUserMonth tmStat2CUserMonth, TMStat2CUserDayTransCount tMStat2CUserDayTransCount) {

        /* 对客活动月统计表-累计优惠笔数 */
        tmStat2CUserMonth.setTotalQtyAcc(new BigDecimal(tmStat2CUserMonth.getTotalQtyAcc()).add(new BigDecimal(tMStat2CUserDayTransCount.getDayPaymentCount())).subtract(new BigDecimal(tMStat2CUserDayTransCount.getDayRefundCount())).toString());
    }

    /**
     * 对客活动统计表赋值
     *
     * @param tmStat2C    对客活动统计表
     * @param tmStat2CDay 对客活动单日统计
     * @author liujinan
     * @since 2021/7/12 11:23
     */
    private void copytmStat2CData(TMStat2C tmStat2C, TMStat2CDay tmStat2CDay) {

        /* 对客活动统计表-总预算累计消耗笔数 */
        tmStat2C.setTotalQtyAcc(new BigDecimal(tmStat2C.getTotalQtyAcc()).add(new BigDecimal(tmStat2CDay.getTotalQtyAcc())).toString());
        /* 对客活动统计表-总预算累计消耗金额 */
        tmStat2C.setTotalAmtAcc(new BigDecimal(tmStat2C.getTotalAmtAcc()).add(new BigDecimal(tmStat2CDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 对客活动商户统计表赋值
     *
     * @param tmStat2CMchnt    对客活动商户统计表
     * @param tmStat2CMchntDay 对客活动商户单日统计
     * @author liujinan
     * @since 2021/7/12 11:23
     */
    private void copytmStat2CMchntData(TMStat2CMchnt tmStat2CMchnt, TMStat2CMchntDay tmStat2CMchntDay) {

        /* 对客活动统计表-总预算累计消耗笔数 */
        tmStat2CMchnt.setTotalQtyAcc(new BigDecimal(tmStat2CMchnt.getTotalQtyAcc()).add(new BigDecimal(tmStat2CMchntDay.getTotalQtyAcc())).toString());
        /* 对客活动统计表-总预算累计消耗金额 */
        tmStat2CMchnt.setTotalAmtAcc(new BigDecimal(tmStat2CMchnt.getTotalAmtAcc()).add(new BigDecimal(tmStat2CMchntDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt    手续费减免活动商户统计表
     * @param tmStatMfdMchntDay 手续费减免活动商户单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntStatMfdData(TMStatMfdMchnt tmStatMfdMchnt, TMStatMfdMchntDay tmStatMfdMchntDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTotalQtyAcc(new BigDecimal(tmStatMfdMchnt.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTotalAmtAcc(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTxnQtyAcc(new BigDecimal(tmStatMfdMchnt.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTxnAmtAcc(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 手续费减免活动统计数据赋值
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyStatMfdData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTotalQtyAcc(new BigDecimal(tmStatMfd.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTxnQtyAcc(new BigDecimal(tmStatMfd.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTxnAmtAcc(new BigDecimal(tmStatMfd.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 根据上送的json字符串 用逗号拼接
     *
     * @return
     * @author liujinan
     * @date 20201.9.1
     */
    private String getUserList() {
        String userIdList = "";
        if (!StringUtil.isNullorEmpty(phoneNo)) {
            userIdList = userIdList + phoneNo + ",";
        }
        if (!StringUtil.isNullorEmpty(cardNo)) {
            userIdList = userIdList + cardNo + ",";
        }
        if (!StringUtil.isNullorEmpty(wechatId)) {
            userIdList = userIdList + wechatId + ",";
        }
        if (!StringUtil.isNullorEmpty(alipayId)) {
            userIdList = userIdList + alipayId + ",";
        }
        if (!StringUtil.isNullorEmpty(coreComId)) {
            userIdList = userIdList + coreComId + ",";
        }
        return userIdList;
    }
}

